首页 > 编程语言 > 详细

linux下socket多线程编程之多人聊天室

时间:2021-03-17 00:25:20      阅读:88      评论:0      收藏:0      [点我收藏+]

关于socket方面这位大佬写的很详细,请参考https://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html

服务端

 #include<sys/socket.h>
 #include<sys/types.h>
 #include<unistd.h>
 #include<arpa/inet.h>
 #include<iostream>
 #include<cstring>
 #include<cstdlib>
 #include<netinet/in.h>
 #include<errno.h>
 #include<thread>
 #include<vector>
 #include<string>
 #define MAXLEN 1024
 
 
 std::vector<int> users;    //保存用户组(已连接套接字)
 
 void sendMsg(int fromfd, char* buff){
     for(int v: users){    //转发给所有用户
         if(v != fromfd)
             if(send(v, buff, strlen(buff), 0) == -1){
                 std::cout << "发送失败:" << strerror(errno) << std::endl;                 
	         return;
             }
     }
 }
 
 void recvMsg(int fd){
     char getbuff[MAXLEN] = {0};
     char buff[MAXLEN] = {0};
     while(1){
         memset(getbuff, 0, MAXLEN);
         memset(buff,0, MAXLEN);
 
         if((recv(fd, getbuff, MAXLEN, 0)) == -1){
             std::cout << "接收信息失败\n";
             continue;
         }
 
         std::cout << "收到消息-->(" << getbuff << ")" << std::endl;
         if(strcmp(getbuff, "bye") == 0){    //收到bye结束
             break;
         }
 
         strcpy(buff, ">>>");    
         strcat(buff, getbuff);
         sendMsg(fd, buff);
     }
 
     for(auto iter = users.begin(); iter != users.end(); ++iter){    //移除用户
         if(*iter == fd){
             users.erase(iter);
             break;
         }
     }
     close(fd);    //关闭套接字
     std::cout << "一位用户离开,当前连接数为:" << users.size() << std::endl;
 }

 int main(){
     int     listenfd, connfd;
     struct  sockaddr_in seraddr;
 
     if((listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1){
         std::cout << "creat socket error:" << strerror(errno) << std::endl;
         exit(0);
     }
 
     memset(&seraddr, 0, sizeof(seraddr));
     seraddr.sin_family = AF_INET;
     seraddr.sin_port = htons(12345);
     seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
 
     if(bind(listenfd, (struct sockaddr*)&seraddr, sizeof(seraddr)) == -1){    //绑定套接字
         std::cout << "bind socket error:" << strerror(errno) << std::endl;
         exit(0);
     }
 
     if(listen(listenfd, 10) == -1){    //监听
         std::cout << "list error:" << strerror(errno) << std::endl;
         exit(0);
   }
 
     std::cout << "服务已开启,等待用户接入...." << std::endl;
 
     while(1){
         if((connfd = accept(listenfd, (struct sockaddr*)NULL, NULL)) == -1){    //循环等待连接
             std::cout << "connect error:" << strerror(errno) << std::endl;
             exit(0);
         }
 
         users.push_back(connfd);    //加入用户
         std::cout << "一位用户进入聊天室,当前连接数为:" << users.size() << std::endl;
         std::thread t(recvMsg, connfd);    //创建线程处理该套接字的收发消息
         t.detach();    //使线程非阻塞
     }
 
     close(connfd);
     close(listenfd);
 
     return 0;
 }

客户端

 #include<sys/socket.h>
 #include<sys/types.h>
 #include<unistd.h>
 #include<arpa/inet.h>
 #include<iostream>
 #include<string.h>
 #include<stdlib.h>
 #include<errno.h>
 #include<stdio.h>
 #include<thread>
 #define MAXLEN 1024
 
 
 char recvbuff[MAXLEN] = {0};
 char sendbuff[MAXLEN] = {0};
 char getbuff[1000] = {0};
 
 void recvMsg(int fd){    //处理收到的消息
     while(1){
         memset(recvbuff, 0, MAXLEN);
         recv(fd, recvbuff, MAXLEN, 0);
         std::cout << recvbuff << std::endl;
     }
 }
 
 int main(){
     int clientfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     sockaddr_in serveraddr;
 
     memset(&serveraddr, 0, sizeof(serveraddr));
     serveraddr.sin_family = AF_INET;
     serveraddr.sin_addr.s_addr = inet_addr("192.168.0.121");
     serveraddr.sin_port = htons(12345);
 
     char name[20] = {0};
     std::cout << "请输入您的用户名:";
     std::cin.getline(name, 20);
     strcat(name, ":");
 
     if((connect(clientfd, (sockaddr*)&serveraddr, sizeof(serveraddr)) == -1)){
         perror("连接失败\n");
         exit(0);
     }
 
     std::cout << "您已进入聊天室,祝您聊天愉快。" << std::endl;

     std::thread t_(recvMsg, clientfd);
     t_.detach();
 
 
     while(1){
         memset(getbuff, 0, 1004);
         std::cin.getline(getbuff, MAXLEN);
 
         if(strcmp(getbuff, "bye") == 0){
             send(clientfd, getbuff, 1000, 0);
             break;
         }
 
         memset(sendbuff, 0, MAXLEN);
         strcpy(sendbuff, name);
         strcat(sendbuff, getbuff);
 
         if((send(clientfd, sendbuff, MAXLEN, 0) == -1)){
             perror("发送失败\n");
             exit(0);
         }
 
     }
     close(clientfd);
 }

编译参数添加 -std=c++11 -pthread

效果图

技术分享图片

技术分享图片

技术分享图片

linux下socket多线程编程之多人聊天室

原文:https://www.cnblogs.com/Fire-In-Ice/p/14546490.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!