linuxc聊天系统代码(c语言聊天程序代码)[20240430更新]
admin 发布:2024-04-30 06:16 129
今天给各位分享linuxc聊天系统代码的知识,其中也会对c语言聊天程序代码进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
本文目录一览:
- 1、在linux下如何用c语言来写一个socket编程的聊天小程序
- 2、如何编写linux聊天室
- 3、linux C语言 TCP 多线程 简易聊天室
- 4、如何用C语言编写一个简单的聊天室程序
- 5、老师让我在LINUX里用GTK和C语言设计个聊天软件 类似QQ的 必须有界面和基本功能 聊天界面,表情,聊天记录
- 6、关于在linux下用C语言实现多客户端和服务器端聊天的实现!
在linux下如何用c语言来写一个socket编程的聊天小程序
你要去学习linux下进行网络编程的一些函数,比如socket(),listen,accept()等函数.再看点例子就会了
如何编写linux聊天室
自从开始学linux网络编程后就想写个聊天室,一开始原本打算用多进程的方式来写,可是发觉进程间的通信有点麻烦,而且开销也大,后来想用多线程能不能实现呢,于是便去看了一下linux里线程的用法,实际上只需要知道 pthread_create 就差不多了,于是动手开干,用了两天时间,调试的过程挺痛苦的,一开始打算用纯C来撸,便用简单的数组来存储客户端的连接信息,可是运行时出现了一些很奇怪的问题,不知道是不是访问了临界资源,和线程间的互斥有关等等;奇怪的是,当改用STL的set或map时问题就解决了,但上网搜了下发现STL也不是线程安全的,至于到底是什么问题暂时不想去纠结了,可能是其它一些小细节的错误吧。先贴上代码:
首先是必要的头文件 header.h:
#ifndef __HEADER_H#define __HEADER_H#include stdio.h#include stdlib.h#include string.h#include unistd.h#include sys/types.h#include sys/socket.h#include netinet/in.h#include arpa/inet.h#include error.h#include signal.h#include sys/wait.h#include assert.h#include pthread.h#define bool int // the 3 lines is for c originally#define true 1#define false 0#define PORT 9003#define BUF_LEN 1024 // 缓冲区大小#define MAX_CONNECTION 6 // 服务器允许的最大连接数,可自行更改#define For(i,s,t) for(i = (s); i != (t); ++i)#endif // __HEADER_H
然后是客户端部分 client.cpp,相对来说简单一些:
#include "header.h"// 客户端接收消息的线程函数void* recv_func(void *args)
{ char buf[BUF_LEN]; int sock_fd = *(int*)args; while(true) { int n = recv(sock_fd, buf, BUF_LEN, 0); if(n = 0) break; // 这句很关键,一开始不知道可以用这个来判断通信是否结束,用了其它一些很奇葩的做法来结束并关闭 sock_fd 以避免 CLOSE_WAIT 和 FIN_WAIT2 状态的出现T.T write(STDOUT_FILENO, buf, n);
}
close(sock_fd);
exit(0);
}// 客户端和服务端进行通信的处理函数void process(int sock_fd)
{
pthread_t td;
pthread_create(td, NULL, recv_func, (void*)sock_fd); // 新开个线程来接收消息,避免了一读一写的原始模式,一开始竟把它放进 while 循环里面了,泪崩。。。
char buf[BUF_LEN]; while(true) { int n = read(STDIN_FILENO, buf, BUF_LEN);
buf[n++] = '\0'; // 貌似标准读入不会有字符串结束符的,需要自己手动添加
send(sock_fd, buf, n, 0);
}
close(sock_fd);
}int main(int argc, char *argv[])
{
assert(argc == 2); struct sockaddr_in cli;
bzero(cli, sizeof(cli));
cli.sin_family = AF_INET;
cli.sin_addr.s_addr = htonl(INADDR_ANY);
cli.sin_port = htons(PORT); // 少了 htons 的话就连接不上了,因为小端机器的原因???
int sc = socket(AF_INET, SOCK_STREAM, 0); if(sc 0) {
perror("socket error");
exit(-1);
}
inet_pton(AF_INET, argv[1], (cli.sin_addr)); // 用第一个参数作为连接服务器端的地址
int err = connect(sc, (struct sockaddr*)cli, sizeof(cli)); if(err 0) {
perror("connect error");
exit(-2);
}
process(sc);
close(sc); return 0;
}
最后是服务端 server.cpp:
#include map#include "header.h"using std::map;
mapint, struct sockaddr_in* socks; // 用于记录各个客户端,键是与客户端通信 socket 的文件描述符,值是对应的客户端的 sockaddr_in 的信息// 群发消息给 socks 中的所有客户端inline void send_all(const char *buf, int len)
{ for(auto it = socks.begin(); it != socks.end(); ++it)
send(it-first, buf, len, 0);
}// 服务端端接收消息的线程函数void* recv_func(void* args)
{ int cfd = *(int*)args; char buf[BUF_LEN]; while(true) { int n = recv(cfd, buf, BUF_LEN, 0); if(n = 0) break; // 关键的一句,用于作为结束通信的判断 write(STDOUT_FILENO, buf, n); if(strcmp(buf, "bye\n") == 0) { // 如果接收到客户端的 bye,就结束通信并从 socks 中删除相应的文件描述符,动态申请的空间也应在删除前释放
printf("close connection with client %d.\n", cfd); free(socks[cfd]);
socks.erase(cfd); break;
}
send_all(buf, n); // 群发消息给所有已连接的客户端 }
close(cfd); // 关闭与这个客户端通信的文件描述符}// 和某一个客户端通信的线程函数void* process(void *argv)
{
pthread_t td;
pthread_create(td, NULL, recv_func, (void*)argv); // 在主处理函数中再新开一个线程用于接收该客户端的消息
int sc = *(int*)argv; char buf[BUF_LEN]; while(true) { int n = read(STDIN_FILENO, buf, BUF_LEN);
buf[n++] = '\0'; // 和客户端一样需要自己手动添加字符串结束符
send_all(buf, n); // 服务端自己的信息输入需要发给所有客户端 }
close(sc);
}int main(int argc, char *argv[])
{ struct sockaddr_in serv;
bzero(serv, sizeof(serv));
serv.sin_family = AF_INET;
serv.sin_addr.s_addr = htonl(INADDR_ANY);
serv.sin_port = htons(PORT); int ss = socket(AF_INET, SOCK_STREAM, 0); if(ss 0) {
perror("socket error"); return 1;
} int err = bind(ss, (struct sockaddr*)serv, sizeof(serv)); if(err 0) {
perror("bind error"); return 2;
}
err = listen(ss, 2); if(err 0) {
perror("listen error"); return 3;
}
socks.clear(); // 清空 map
socklen_t len = sizeof(struct sockaddr); while(true) { struct sockaddr_in *cli_addr = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in)); int sc = accept(ss, (struct sockaddr*)cli_addr, len); if(sc 0) { free(cli_addr); continue;
} if(socks.size() = MAX_CONNECTION) { // 当将要超过最大连接数时,就让那个客户端先等一下
char buf[128] = "connections is too much, please waiting...\n";
send(sc, buf, strlen(buf) + 1, 0);
close(sc); free(cli_addr); continue;
}
socks[sc] = cli_addr; // 指向对应申请到的 sockaddr_in 空间
printf("client %d connect me...\n", sc);
pthread_t td;
pthread_create(td, NULL, process, (void*)sc); // 开一个线程来和 accept 的客户端进行交互 } return 0;
}
makefile文件:
all: server client
server: server.cpp
g++ -std=c++11 -o server server.cpp -lpthread
client: client.cpp
g++ -std=c++11 -o client client.cpp -lpthread
clean:
rm -f *.o
在我的ubuntu 14.04 64 位的机器上测试过没有什么问题,客户端与服务端能正常的交互和退出,能通过服务端接收其它客户端发送的消息,运行时cpu和内存占用情况正常,不会产生什么奇怪的bug。暂时只写了个终端的界面,客户端的UI迟点再去弄吧~
*****************************************************************************************************************************************
今天试了下用 PyQt4 去写个客户端的界面,调了好一天,总算能看到点东西了,先上图:
而命令行下的客户端(上面的 client.cpp 文件)的运行界面是这样子的:
服务端的运行情况是:
PyQt4 编写的客户端(pyqt_client.py)代码是:
#!/usr/bin/env python#-*- coding: utf-8 -*-from PyQt4 import QtGui, QtCoreimport sysimport socketimport threadclass Client(QtGui.QWidget):
BUF_LEN = 1024 def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setWindowTitle(u'TCP客户端')
self.resize(600, 500)
self.center()
layout = QtGui.QGridLayout(self)
label_ip = QtGui.QLabel(u'远程主机IP:')
layout.addWidget(label_ip, 0, 0, 1, 1)
self.txt_ip = QtGui.QLineEdit('127.0.0.1')
layout.addWidget(self.txt_ip, 0, 1, 1, 3)
label_port = QtGui.QLabel(u'端口:')
layout.addWidget(label_port, 0, 4, 1, 1)
self.txt_port = QtGui.QLineEdit('9003')
layout.addWidget(self.txt_port, 0, 5, 1, 3)
self.isConnected = False
self.btn_connect = QtGui.QPushButton(u'连接')
self.connect(self.btn_connect, QtCore.SIGNAL( 'clicked()'), self.myConnect)
layout.addWidget(self.btn_connect, 0, 8, 1, 2)
label_recvMessage = QtGui.QLabel(u'消息内容:')
layout.addWidget(label_recvMessage, 1, 0, 1, 1)
self.btn_clearRecvMessage = QtGui.QPushButton(u'↓ 清空消息框')
self.connect(self.btn_clearRecvMessage, QtCore.SIGNAL( 'clicked()'), self.myClearRecvMessage)
layout.addWidget(self.btn_clearRecvMessage, 1, 7, 1, 3)
self.txt_recvMessage = QtGui.QTextEdit()
self.txt_recvMessage.setReadOnly(True)
self.txt_recvMessage.setStyleSheet('background-color:yellow')
layout.addWidget(self.txt_recvMessage, 2, 0, 1, 10)
lable_name = QtGui.QLabel(u'姓名(ID):')
layout.addWidget(lable_name, 3, 0, 1, 1)
self.txt_name = QtGui.QLineEdit()
layout.addWidget(self.txt_name, 3, 1, 1, 3)
self.isSendName = QtGui.QRadioButton(u'发送姓名')
self.isSendName.setChecked(False)
layout.addWidget(self.isSendName, 3, 4, 1, 1)
label_sendMessage = QtGui.QLabel(u' 输入框:')
layout.addWidget(label_sendMessage, 4, 0, 1, 1)
self.txt_sendMessage = QtGui.QLineEdit()
self.txt_sendMessage.setStyleSheet("background-color:cyan")
layout.addWidget(self.txt_sendMessage, 4, 1, 1, 7)
self.btn_send = QtGui.QPushButton(u'发送')
self.connect(self.btn_send, QtCore.SIGNAL('clicked()'), self.mySend)
layout.addWidget(self.btn_send, 4, 8, 1, 2)
self.btn_clearSendMessage = QtGui.QPushButton(u'↑ 清空输入框')
self.connect(self.btn_clearSendMessage, QtCore.SIGNAL( 'clicked()'), self.myClearSendMessage)
layout.addWidget(self.btn_clearSendMessage, 5, 6, 1, 2)
self.btn_quit = QtGui.QPushButton(u'退出')
self.connect(self.btn_quit, QtCore.
linux C语言 TCP 多线程 简易聊天室
你accept得到一个新的连接后,再创建线程(把连接socket传给线程),用这个线程专门接收这个连接的数据,就不会有问题了。
如何用C语言编写一个简单的聊天室程序
这样:
#include stdlib.h
#include stdio.h
#include errno.h
#include string.h
#include unistd.h
#include netdb.h
#include sys/socket.h
#include netinet/in.h
#include sys/types.h
#include arpa/inet.h
#include pthread.h
#define MAXLINE 100;
void *threadsend(void *vargp);
void *threadrecv(void *vargp);
int main()
{
int *clientfdp;
clientfdp = (int *)malloc(sizeof(int));
*clientfdp = socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in serveraddr;
struct hostent *hp;
bzero((char *)serveraddr,sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(15636);
serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
if(connect(*clientfdp,(struct sockaddr *)serveraddr,sizeof(serveraddr)) 0){
printf("connect error\n");
exit(1);
}
pthread_t tid1,tid2;
printf("connected\n");
while(1){
pthread_create(tid1,NULL,threadsend,clientfdp);
pthread_create(tid2,NULL,threadrecv,clientfdp);
}
return EXIT_SUCCESS;
}
void *threadsend(void * vargp)
{
//pthread_t tid2;
int connfd = *((int *)vargp);
int idata;
char temp[100];
while(1){
//printf("me: \n ");
fgets(temp,100,stdin);
send(connfd,temp,100,0);
printf(" client send OK\n");
}
printf("client send\n");
return NULL;
}
void *threadrecv(void *vargp)
{
char temp[100];
int connfd = *((int *)vargp);
while(1){
int idata = 0;
idata = recv(connfd,temp,100,0);
if(idata 0){
printf("server :\n%s\n",temp);
}
}
return NULL;
}
扩展资料:
注意事项
linux下编译多线程代码时,shell提示找不到 pthread_create函数,原因是 pthread.h不是linux系统默认加载的库文件,应该使用类似如下gcc命令进行编译:
gcc echoserver.c -lpthread -o echoserver
只要注意 -lpthread参数就可以了。
老师让我在LINUX里用GTK和C语言设计个聊天软件 类似QQ的 必须有界面和基本功能 聊天界面,表情,聊天记录
GTK是C++类库吧,怎么用C语言来写界面,你老师脑残了啊
你可以去问候他老母或者自己找下GTK的资料,socket是关键,多线程和并发什么的,不要偷懒,不然出来工作就跟个傻瓜一样了
关于在linux下用C语言实现多客户端和服务器端聊天的实现!
你的意思是服务器监听同一端口,然后根据不同客户端运行不同的服务器程序?如果是,自然少不了select或if-elseif-then
linuxc聊天系统代码的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于c语言聊天程序代码、linuxc聊天系统代码的信息别忘了在本站进行查找喔。
版权说明:如非注明,本站文章均为 AH站长 原创,转载请注明出处和附带本文链接;
相关推荐
- 05-03订单进度代码(订单进度表)[20240503更新]
- 05-03在线客服网站代码(在线客服网站代码查询)[20240503更新]
- 05-03五子棋vb代码(vb五子棋游戏程序设计)[20240503更新]
- 05-02安卓消息播放提示音源代码(安卓原生提示音)[20240502更新]
- 05-02matlab随机共振代码(matlab振荡环节仿真)[20240502更新]
- 05-02dftc代码(dfa代码)[20240502更新]
- 05-02滚动代码生成器(滚动代码生成器手机版)[20240502更新]
- 05-02自动投票代码(自动投票代码大全)[20240502更新]
- 05-02bp神经网络在matlab代码(matlab中bp神经网络)[20240502更新]
- 05-02网页点击进入主页代码(web登录页面代码)[20240502更新]
取消回复欢迎 你 发表评论:
- 标签列表
- 最近发表
- 友情链接