socket利用多线程实现一对多通信
1、服务器端:socket()建立套接字,绑定(bind)并监听(listen),用accept()等待客户端连接。将accept()写入死循环,每次连接一个客户端,开一个线程。
2、一般情况下建立socket连接后服务器与客户端建立了一个管道,当关闭socket或关闭客户端的时候,会导致管道破裂信号。如果使用默认处理则会导致服务器程序退出。
需要程序忽略管道破裂信号。
signal(SIGPIPE, SIG_IGN);//忽略管道破裂信号
3、线程处理完毕后,需要及时关闭线程,通过recv()函数的特性,在socket关闭的时候返回零。判断并结束线程。
#include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <pthread.h> #include <sys/socket.h> #include <arpa/inet.h> #include <signal.h> //处理信号问题 应忽略socket 信号 #define MY_IP "192.168.149.137" #define MY_PORT 5005 #define BACKLOG 100 #define DEBUF(X) printf(X) int fd = -1; char buf[100]; //最大连接数 void *func(void *arg) { char recv_buf[100]; char send_buf[100]; int client_fd = (int)arg;//传参 int ret = 1; memset(recv_buf,0,sizeof(recv_buf)); while(1) { ret = recv(client_fd,&recv_buf,sizeof(recv_buf),0); if(0 == ret) break;//阻塞等待过程中断开则会返回0 printf("%s\n",recv_buf); send(client_fd,&recv_buf,sizeof(recv_buf),0); memset(recv_buf,0,sizeof(recv_buf)); } printf("over \n"); } int main() { struct sockaddr_in server_addr; struct sockaddr_in client_addr;//客户地址 socklen_t len = 0;//接收长度 char recv_buf[100]; char send_buf[100]; int sock_fd = -1;//监听描述符 int client_fd = -1;//连接fd int ret = -1; pthread_t th =-1 ; signal(SIGPIPE, SIG_IGN);//忽略管道破裂信号 sock_fd = socket(AF_INET,SOCK_STREAM,0); if(-1 == sock_fd) { perror("socket"); return -1; } printf("sock_fd = %d.\n",sock_fd); //2.bind绑定socket 和本机IP 端口 server_addr.sin_family = AF_INET;//IPV4 server_addr.sin_port = htons(MY_PORT);//设置端口模式 server_addr.sin_addr.s_addr = inet_addr(MY_IP);//设置IP ret = bind(sock_fd,(struct sockaddr *)&server_addr,sizeof(server_addr)); if(-1 == ret) { perror("bind"); return -1; } DEBUF("bind ok\n"); //3.listen 设 置监听 ret = listen(sock_fd, BACKLOG);//BACKLOG为排队处理 if(-1 == ret) { perror("listen"); return -1; } DEBUF("listen ok\n"); while(1) { client_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &len); if(-1 == client_fd) { perror("listen"); return -1; } ret = pthread_create(&th ,NULL , func , (void*)client_fd);//创建线程 DEBUF("新用户加入\n"); if(ret != 0) { printf("pthread_create error \n"); return -1; } } return 0; }