Linux下C编写基本的多线程socket服务器

不想多说什么,会搜这些东西的都是想看代码的吧。

一开始不熟悉多线程的时候还在想怎么来控制一个线程的结束,后来发现原来有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 #include<stdlib.h>
  8 #include<pthread.h>
  9 #include<sys/socket.h>
 10 #include<sys/types.h>       //pthread_t , pthread_attr_t and so on.
 11 #include<stdio.h>
 12 #include<netinet/in.h>      //structure sockaddr_in
 13 #include<arpa/inet.h>       //Func : htonl; htons; ntohl; ntohs
 14 #include<assert.h>          //Func :assert
 15 #include<string.h>          //Func :memset
 16 #include<unistd.h>          //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     //Clear
120     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 #include<stdlib.h>
 8 #include<sys/socket.h>
 9 #include<sys/types.h>       //pthread_t , pthread_attr_t and so on.
10 #include<stdio.h>
11 #include<netinet/in.h>      //structure sockaddr_in
12 #include<arpa/inet.h>       //Func : htonl; htons; ntohl; ntohs
13 #include<assert.h>          //Func :assert
14 #include<string.h>          //Func :memset
15 #include<unistd.h>          //Func :close,write,read
16 #define SOCK_PORT 9988
17 #define BUFFER_LENGTH 1024
18 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,TCP
29     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_t
38     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 this
53         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 client
61         {
62             break;
63         }
64         else
65         {
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()--<unistd.h> to close the fd
75     assert(ret != -1);
76     return 0;
77 }

 

posted @ 2014-03-15 17:02  NeroHwang  阅读(18509)  评论(0编辑  收藏  举报