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; }