Linux C利用Socket套接字进行服务器与多个客户端进行通讯 您所在的位置:网站首页 如何编写套接字 Linux C利用Socket套接字进行服务器与多个客户端进行通讯

Linux C利用Socket套接字进行服务器与多个客户端进行通讯

2024-07-05 11:14| 来源: 网络整理| 查看: 265

代码思路:

服务器端:首先创建监听的套接字,然后创建用于(循环检测客户端连接)的新线程,当检测到有客户端连接,则创建一个新的线程负责同这个套接字通讯,即接受这个套接字发送过来的消息。

 

现象:

单个客户端同服务器可以进行通讯,当连接上多个客户端过后,服务器端能够群发消息,最后连接的客户端向服务器发送的消息能够接受到,但之前的所有的客户端向服务器发送消息均不能收到。

 

解决思路:

先使用排除法,首先找到了一份正确的客户端代码,连接上我自己写的服务器,也出现了同样的错误,所以可以排除我自己写的客户端。最终到了服务器端。服务器中,因为单个客户端可以与服务器通讯,所以检测连接的线程没有问题,那么最终归结到了循环接受客户端数据的线程。那着正确的服务器接受客户端数据的代码同自己写的对照,哈哈,发现了问题,是_socketCon值的问题,_socketCon的赋值是通过指针,然后打印这个值,发现这个值在不断变化,并且在检测连接的线程中定义的 int socketCon 值正是这个,而这个值是在 while死循环中不停的创建,不停的销毁!哇咔咔,真相终于大白与天下,功夫不负有心人啊,查了一天半的bug终于被我查出来了!

总结:

1、在死循环中切记不要定义变量,最好是在死循环之外定义变量,在死循环中使用!

2、在函数有死循环时,值只有一个的局部变量,就在死循环之上定义并初始化!就不要在死循环中赋值,只是去使用它就好了!

3、在创建多线程给多线程处理函数传参数中,切记不要传入生命周期较短的指针变量,传入值类型都好!

  服务器端故障代码如下 void *fun_thrReceiveHandler(void *socketCon){ char buffer[30]; int buffer_length; int _socketCon; while(1){ //添加对buffer清零 bzero(&buffer,sizeof(buffer)); _socketCon = *((int *)socketCon); sleep(0.1); printf("接受数据线程中,连接套接字为%d\n",_socketCon); buffer_length = read(_socketCon,buffer,30); if(buffer_length == 0){ printf("%d 客户端关闭\n",_socketCon); conClientCount--; break; }else if(buffer_length < 0){ printf("接受客户端数据失败\n"); break; } buffer[buffer_length] = '\0'; printf("%d 说:%s\n",_socketCon,buffer); //获取当前线程id //printf("当前线程id:%ld",pthread_self()); sleep(0.2); } printf("接受数据线程结束了\n"); return NULL; } 服务器与多个客户端通讯的正确代码如下:

服务器端 - socket_server.c

#include #include #include #include #include #include #include #include #include //服务器端 void *fun_thrReceiveHandler(void *socketInfo); void *fun_thrAcceptHandler(void *socketListen); //1:是 0:否 int checkThrIsKill(pthread_t thr); typedef struct MySocketInfo{ int socketCon; char *ipaddr; uint16_t port; }_MySocketInfo; // 客户端数组 struct MySocketInfo arrConSocket[10]; int conClientCount = 0; // 接受客户端线程列表 pthread_t arrThrReceiveClient[10]; int thrReceiveClientCount = 0; int main() { //初始化全局变量 //memset(arrConSocket,0,sizeof(struct MySocketInfo)*10); printf("开始socket\n"); /* 创建TCP连接的Socket套接字 */ int socketListen = socket(AF_INET, SOCK_STREAM, 0); if(socketListen < 0){ printf("创建TCP套接字失败\n"); exit(-1); }else{ printf("创建套接字成功\n"); } /* 填充服务器端口地址信息,以便下面使用此地址和端口监听 */ struct sockaddr_in server_addr; bzero(&server_addr,sizeof(struct sockaddr_in)); server_addr.sin_family=AF_INET; server_addr.sin_addr.s_addr=htonl(INADDR_ANY); /* 这里地址使用全0,即所有 */ server_addr.sin_port=htons(2000); if(bind(socketListen, (struct sockaddr *)&server_addr,sizeof(struct sockaddr)) != 0){ perror("绑定ip地址、端口号失败\n"); exit(-1); }else{ printf("绑定ip地址,端口号\n"); } /* 开始监听相应的端口 */ if(listen(socketListen, 10) != 0){ printf("开启监听失败\n"); exit(-1); }else{ printf("开启监听成功\n"); } /* 接受连接套接字 */ pthread_t thrAccept; pthread_create(&thrAccept,NULL,fun_thrAcceptHandler,&socketListen); /* 实时发送数据 */ while(1){ //判断线程存活多少 int i; for(i=0;i


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有