300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > Linux下c语言TCP多线程聊天室

Linux下c语言TCP多线程聊天室

时间:2022-01-05 05:32:18

相关推荐

Linux下c语言TCP多线程聊天室

前言

开发环境:Linux(ubuntu 12.04),GCC

编译:

gcc server.c -lpthread -std=gnu99 -o sgcc client.c -lpthread -std=gnu99 -o c

相关知识:TCP(博客:传送门),线程

附加:项目可能还有写不足之处,有些bug没调出来(如:对在线人数的控制)。

效果图

运行服务端

运行2个客户端

其中一个客户端发送消息

互相发送

整体效果图

客户端发送"quit"断开连接。

代码下载

那么话不多说,放码过来:

码云:传送门,GitHub:传送门

代码

服务端:server.c

#include <stdio.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <string.h>#include <pthread.h>struct sockaddr_in addr = {};int clifd_index = 0; // clifd的下标char buf[1024] = {}; // 存储客户端发来的字符串char str[1024] = {}; // 存储带clifd的回传信息int clifd[30] = {}; // 存储clifdint online_num = 0;// 连接人数int max_num = 10; // 最大人数// 项目有bug,连接人数的限制控制不住,有待改进void* start_read(void *arg) // 读取信息的子线程{//printf("arg:%d\n",*(int*)arg);int clifd1 = *(int*)arg;printf("run_clifd:%d\n",clifd1);for(;;){//printf("before read\n");int ret = read(clifd1,buf,sizeof(buf));printf("\nip:%s,port:%hu,size:%d\n",inet_ntoa(addr.sin_addr),ntohs(addr.sin_port),ret); // 获取相关信息printf("say:%s\n",buf);char id[10] = {};sprintf(id,"%d说:",clifd1);if(strlen(buf) != 0){strcpy(str,id);strcat(str,buf);} // 存入str中if(0 == strcmp("quit",buf)) // 如果收到quit{online_num--; // 在线人数-1for(int i=0; i<clifd_index; i++){if(clifd1 == clifd[i]){int *die = &clifd1;clifd[i] = 0;pthread_exit(die); // 终止线程break;}}}//usleep(1000);}}void* start_write(void *arg) // 写回的子线程{//printf("arg:%d\n",*(int*)arg);//usleep(500);int clifd1 = *(int*)arg;printf("run_clifd:%d\n",clifd1);for(;;){int flag = 0;for(int i=0; i<clifd_index; i++) // 因为读到quit的原因,clifd被置0{if(clifd1 == clifd[i]){break;}if(i == clifd_index-1){int *die = &clifd1;flag = 1;pthread_exit(die); // 终止此写回的子线程}}if(flag == 1){break;}if(strlen(str) == 0) // 空消息不写入continue;printf("before write\n");printf("str:%s\n",str);write(clifd1,str,strlen(str)+1);usleep(50000); // 最快的子线程等待其他子线程memset(str,0,1024); // 清空str}}int main(){printf("服务器创建socket...\n");int sockfd = socket(AF_INET,SOCK_STREAM,0);if(0 > sockfd){perror("socket");return -1;}printf("准备地址...\n");addr.sin_family = AF_INET;addr.sin_port = htons(6008);//端口号addr.sin_addr.s_addr = inet_addr("127.0.0.1");//你的ip地址(或服务器的私网ip)socklen_t len = sizeof(addr);printf("绑定socket与地址...\n");if(bind(sockfd,(struct sockaddr*)&addr,len)){perror("bind");return -1;}printf("设置监听...\n");if(listen(sockfd,2)){perror("listen");return -1;}printf("等待客户端连接...\n");for(;;){if(online_num < max_num){struct sockaddr_in addrcli = {};clifd[clifd_index] = accept(sockfd,(struct sockaddr*)&addrcli,&len);int flag = 0;for(int i=0; i<clifd_index; i++){if(clifd[clifd_index] == clifd[i]){flag = 1;break;}}if(flag == 1){clifd_index--;continue;}else{char link[50] = {};char link1[40] = "您已经成功连接";sprintf(link,"您的id是:%d,",clifd[clifd_index]);strcat(link,link1);write(clifd[clifd_index],link,strlen(link)+1);online_num++;}}else{continue;}if(0 > clifd[clifd_index]){perror("accept");continue;}printf("clifd:%d\n",clifd[clifd_index]);// 创建子线程pthread_t pid1,pid2;pthread_create(&pid1,NULL,start_read,&clifd[clifd_index]);pthread_create(&pid2,NULL,start_write,&clifd[clifd_index]);usleep(1000);//printf("clifd:%d\n",clifd[index]);clifd_index++; // 下标逐渐+1,这样写不是很合适}return 0;}

客户端:client.c

#include <stdio.h>#include <unistd.h>#include <arpa/inet.h>#include <string.h>#include <pthread.h>void* start_read(void* arg) // 读取信息{int sockfd = *(int*)arg;char buf[1024] = {};for(;;){read(sockfd,buf,sizeof(buf));if(strlen(buf) != 0){printf("\n>%s\n",buf);}}}int main(){printf("服务器创建socket...\n");int sockfd = socket(AF_INET,SOCK_STREAM,0);if(0 > sockfd){perror("socket");return -1;}printf("准备地址...\n");struct sockaddr_in addr = {};addr.sin_family = AF_INET;addr.sin_port = htons(6008);//设置的端口号addr.sin_addr.s_addr = inet_addr("127.0.0.1");//你的ip地址(或服务器的公网ip)socklen_t len = sizeof(addr);printf("绑定连接服务器...\n");if(connect(sockfd,(struct sockaddr*)&addr,len)){perror("connect");return -1;}char link[50] = {};read(sockfd,link,sizeof(link));//printf("link:%s\n",link);if(strstr(link,"您已经成功连接")==NULL){printf("连接人数已满,请稍后重试\n");return 0;}else{printf("link:%s\n",link);}// 创建读取子线程pthread_t pid;pthread_create(&pid,NULL,start_read,&sockfd);for(;;){char buf[1024] = {};usleep(1000);//printf(">我说:");gets(buf);write(sockfd,buf,strlen(buf)+1);if(0 == strcmp("quit",buf)){printf("通信结束!\n");break;}}close(sockfd);}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。