不想多说什么,会搜这些东西的都是想看代码的吧。
一开始不熟悉多线程的时候还在想怎么来控制一个线程的结束,后来发现原来有pthread_exit()函数可以直接在线程函数内部调用结束这个线程。
开始还想初始化一个pthread_t thread_fd[MAX]数组来存储开启的线程,然后用一个栈存储那些未分配的数组元素(thread_fd[index]=0)的index,跟缓存的思维相似,不过实在是想多了。
废话不多说,直接上代码,服务器和客户端都已经编译通过,正常运行,有基本的容错能力,不过也只是最基本的。
服务器:
1 /* 2 * multi_thread_socket_server.c 3 * 4 * Created on: Mar 14, 2014 5 * Author: nerohwang 6 */ 7 #include8 #include 9 #include 10 #include //pthread_t , pthread_attr_t and so on. 11 #include 12 #include //structure sockaddr_in 13 #include //Func : htonl; htons; ntohl; ntohs 14 #include //Func :assert 15 #include //Func :memset 16 #include //Func :close,write,read 17 #define SOCK_PORT 9988 18 #define BUFFER_LENGTH 1024 19 #define MAX_CONN_LIMIT 512 //MAX connection limit 20 21 static void Data_handle(void * sock_fd); //Only can be seen in the file 22 23 int main() 24 { 25 int sockfd_server; 26 int sockfd; 27 int fd_temp; 28 struct sockaddr_in s_addr_in; 29 struct sockaddr_in s_addr_client; 30 int client_length; 31 32 sockfd_server = socket(AF_INET,SOCK_STREAM,0); //ipv4,TCP 33 assert(sockfd_server != -1); 34 35 //before bind(), set the attr of structure sockaddr. 36 memset(&s_addr_in,0,sizeof(s_addr_in)); 37 s_addr_in.sin_family = AF_INET; 38 s_addr_in.sin_addr.s_addr = htonl(INADDR_ANY); //trans addr from uint32_t host byte order to network byte order. 39 s_addr_in.sin_port = htons(SOCK_PORT); //trans port from uint16_t host byte order to network byte order. 40 fd_temp = bind(sockfd_server,(struct scokaddr *)(&s_addr_in),sizeof(s_addr_in)); 41 if(fd_temp == -1) 42 { 43 fprintf(stderr,"bind error!\n"); 44 exit(1); 45 } 46 47 fd_temp = listen(sockfd_server,MAX_CONN_LIMIT); 48 if(fd_temp == -1) 49 { 50 fprintf(stderr,"listen error!\n"); 51 exit(1); 52 } 53 54 while(1) 55 { 56 printf("waiting for new connection...\n"); 57 pthread_t thread_id; 58 client_length = sizeof(s_addr_client); 59 60 //Block here. Until server accpets a new connection. 61 sockfd = accept(sockfd_server,(struct sockaddr_*)(&s_addr_client),(socklen_t *)(&client_length)); 62 if(sockfd == -1) 63 { 64 fprintf(stderr,"Accept error!\n"); 65 continue; //ignore current socket ,continue while loop. 66 } 67 printf("A new connection occurs!\n"); 68 if(pthread_create(&thread_id,NULL,(void *)(&Data_handle),(void *)(&sockfd)) == -1) 69 { 70 fprintf(stderr,"pthread_create error!\n"); 71 break; //break while loop 72 } 73 } 74 75 //Clear 76 int ret = shutdown(sockfd_server,SHUT_WR); //shut down the all or part of a full-duplex connection. 77 assert(ret != -1); 78 79 printf("Server shuts down\n"); 80 return 0; 81 } 82 83 static void Data_handle(void * sock_fd) 84 { 85 int fd = *((int *)sock_fd); 86 int i_recvBytes; 87 char data_recv[BUFFER_LENGTH]; 88 const char * data_send = "Server has received your request!\n"; 89 90 while(1) 91 { 92 printf("waiting for request...\n"); 93 //Reset data. 94 memset(data_recv,0,BUFFER_LENGTH); 95 96 i_recvBytes = read(fd,data_recv,BUFFER_LENGTH); 97 if(i_recvBytes == 0) 98 { 99 printf("Maybe the client has closed\n");100 break;101 }102 if(i_recvBytes == -1)103 {104 fprintf(stderr,"read error!\n");105 break;106 }107 if(strcmp(data_recv,"quit")==0)108 {109 printf("Quit command!\n");110 break; //Break the while loop.111 }112 printf("read from client : %s\n",data_recv);113 if(write(fd,data_send,strlen(data_send)) == -1)114 {115 break;116 }117 }118 119 //Clear120 printf("terminating current client_connection...\n");121 close(fd); //close a file descriptor.122 pthread_exit(NULL); //terminate calling thread!123 }
外加客户端:
1 /* 2 * socket_client.c 3 * 4 * Created on: Mar 15, 2014 5 * Author: nerohwang 6 */ 7 #include8 #include 9 #include //pthread_t , pthread_attr_t and so on.10 #include 11 #include //structure sockaddr_in12 #include //Func : htonl; htons; ntohl; ntohs13 #include //Func :assert14 #include //Func :memset15 #include //Func :close,write,read16 #define SOCK_PORT 998817 #define BUFFER_LENGTH 102418 int main()19 {20 int sockfd;21 int tempfd;22 struct sockaddr_in s_addr_in;23 char data_send[BUFFER_LENGTH];24 char data_recv[BUFFER_LENGTH];25 memset(data_send,0,BUFFER_LENGTH);26 memset(data_recv,0,BUFFER_LENGTH);27 28 sockfd = socket(AF_INET,SOCK_STREAM,0); //ipv4,TCP29 if(sockfd == -1)30 {31 fprintf(stderr,"socket error!\n");32 exit(1);33 }34 35 //before func connect, set the attr of structure sockaddr.36 memset(&s_addr_in,0,sizeof(s_addr_in));37 s_addr_in.sin_addr.s_addr = inet_addr("127.0.0.1"); //trans char * to in_addr_t38 s_addr_in.sin_family = AF_INET;39 s_addr_in.sin_port = htons(SOCK_PORT);40 41 tempfd = connect(sockfd,(struct sockaddr *)(&s_addr_in),sizeof(s_addr_in));42 if(tempfd == -1)43 {44 fprintf(stderr,"Connect error! \n");45 exit(1);46 }47 48 while(1)49 {50 printf("Please input something you wanna say(input \"quit\" to quit):\n");51 gets(data_send);52 //scanf("%[^\n]",data_send); //or you can also use this53 tempfd = write(sockfd,data_send,BUFFER_LENGTH);54 if(tempfd == -1)55 {56 fprintf(stderr,"write error\n");57 exit(0);58 }59 60 if(strcmp(data_send,"quit") == 0) //quit,write the quit request and shutdown client61 {62 break;63 }64 else65 {66 tempfd = read(sockfd,data_recv,BUFFER_LENGTH);67 assert(tempfd != -1);68 printf("%s\n",data_recv);69 memset(data_send,0,BUFFER_LENGTH);70 memset(data_recv,0,BUFFER_LENGTH);71 }72 }73 74 int ret = shutdown(sockfd,SHUT_WR); //or you can use func close()-- to close the fd75 assert(ret != -1);76 return 0;77 }