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 }

 

你可能感兴趣的:(socket)