一个采用POSIX线程实现的简易时间服务器,服务端口为4321,客户使用Telnet连上就能看到欢迎消息以及当前服务器时间。
采用主线程accept,然后新建线程处理连接的结构。
代码中自定义了一个结构体struct client_info作为传入每个线程的参数,包含客户的连接fd,客户的sockaddr信息,用于回显消息。
代码如下:
1 #include <unistd.h> 2 #include <pthread.h> 3 #include <sys/socket.h> 4 5 #include <arpa/inet.h> 6 #include <netinet/in.h> 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <errno.h> 12 13 #define SERV_PORT 4321 14 15 struct client_info 16 { 17 int clientfd; 18 struct sockaddr_in clientaddr; 19 socklen_t clientlen; 20 }; 21 22 void 23 rep_err(const char *msg) 24 { 25 fprintf(stderr, "%s\n", msg); 26 perror("TIME_SERVER"); 27 exit(-1); 28 } 29 30 void *slaver(void *); 31 32 int 33 main(int argc, char *argv[]) 34 { 35 pthread_t tid; 36 int listenfd, connfd, err; 37 struct sockaddr_in servaddr, clientaddr; 38 socklen_t clientlen; 39 struct client_info *info; 40 if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) <= 0) 41 rep_err("SOCKET"); 42 43 memset(&servaddr, 0, sizeof(servaddr)); 44 servaddr.sin_family = AF_INET; 45 servaddr.sin_port = htons(SERV_PORT); 46 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 47 48 if((err = bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr))) < 0) 49 rep_err("BIND"); 50 51 if((err = listen(listenfd, 128)) < 0) 52 rep_err("LISTEN"); 53 54 for(;;) 55 { 56 clientlen = sizeof(clientlen); 57 if((connfd = accept(listenfd, (struct sockaddr *)&clientaddr, &clientlen)) <=0) 58 rep_err("ACCEPT"); 59 60 info = (struct client_info *)malloc(sizeof(struct client_info)); 61 info->clientfd = connfd; 62 info->clientaddr = clientaddr; 63 info->clientlen = clientlen; 64 65 pthread_create(&tid, NULL, slaver, (void *)info); 66 } 67 68 exit(0); 69 } 70 71 72 void * 73 slaver(void *info) 74 { 75 pthread_detach(pthread_self()); 76 77 char buffer[256]; 78 char buf[64]; 79 time_t now; 80 time(&now); 81 struct client_info *cinfo = (struct client_info *)info; 82 83 snprintf(buffer, 256, "Welcome %s , from port %d\nNOW IS:\n%s", 84 inet_ntop(AF_INET, &((cinfo->clientaddr).sin_addr), buf, cinfo->clientlen), 85 ntohs(cinfo->clientaddr.sin_port), 86 ctime(&now)); 87 88 write(cinfo->clientfd, buffer, strlen(buffer)); 89 90 close(cinfo->clientfd); 91 92 free(cinfo); 93 94 return NULL; 95 }