这篇是继前三篇并发服务器--01(基于进程派生)、并发服务器--02(基于I/O复用——运用Select函数)和并发服务器--02(基于I/O复用——运用epoll技术)的第4篇关于并发服务器的博文。
关于Linux上多线程详情请参看前一博文Linux多线程编程初探。
本文相对就简陋一点了,只记简单笔记,待后续有更丰富内容再添加。
客户端程序
1 /*#include "unp.h"*/ 2 #include "unpthread.h" 3 4 void *copyto(void *); 5 void str_cli_thread(FILE *fp_arg, int sockfd_arg); 6 static int sockfd; /* global for both threads to access */ 7 static FILE *fp; 8 9 int main(int argc, char **argv) 10 { 11 int sockfd; 12 struct sockaddr_in servaddr; 13 14 if(argc != 2) 15 err_quit("usage: tcpcli <IPaddress>"); 16 17 sockfd = Socket(AF_INET, SOCK_STREAM, 0); 18 19 bzero(&servaddr, sizeof(servaddr)); 20 servaddr.sin_family = AF_INET; 21 servaddr.sin_port = htons(SERV_PORT); 22 Inet_pton(AF_INET, argv[1], &servaddr.sin_addr.s_addr); 23 24 Connect(sockfd, (SA *) &servaddr, sizeof(servaddr)); 25 26 str_cli_thread(stdin, sockfd); 27 28 exit(0); 29 } 30 31 void str_cli_thread(FILE *fp_arg, int sockfd_arg) 32 { 33 char recvline[MAXLINE]; 34 pthread_t tid; 35 36 sockfd = sockfd_arg; 37 fp = fp_arg; 38 39 if(pthread_create(&tid, NULL, copyto, NULL) != 0) 40 { 41 printf("create thread fails"); 42 return; 43 } 44 45 while(Readline(sockfd, recvline, MAXLINE) > 0) 46 Fputs(recvline, stdout); 47 } 48 49 void *copyto(void *arg) 50 { 51 char sendline[MAXLINE]; 52 53 while(Fgets(sendline, MAXLINE, fp) != NULL) 54 Writen(sockfd, sendline, strlen(sendline)); 55 56 Shutdown(sockfd, SHUT_WR); /* EOF on stdin, send FIN */ 57 58 return(NULL); 59 }
编译链接时记得就-lunp和-lpthread。
服务端程序
1 #include "unpthread.h" 2 3 static void *doit(void *); /* each thread executes this function */ 4 5 int main(int argc, char **argv) 6 { 7 int listenfd, *iptr; 8 pthread_t tid; 9 socklen_t addrlen, len; 10 struct sockaddr_in cliaddr, servaddr; 11 12 listenfd = Socket(AF_INET, SOCK_STREAM, 0); 13 14 bzero(&servaddr, sizeof(servaddr)); 15 servaddr.sin_family = AF_INET; 16 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 17 servaddr.sin_port = htons(SERV_PORT); 18 19 Bind(listenfd, (SA *) &servaddr, sizeof(servaddr)); 20 Listen(listenfd, LISTENQ); 21 for( ; ; ) 22 { 23 addrlen = sizeof(cliaddr); 24 iptr = Malloc(sizeof(int)); 25 *iptr = Accept(listenfd, (SA *) &cliaddr, &addrlen); 26 Pthread_create(&tid, NULL, &doit, iptr); 27 } 28 29 exit(0); 30 } 31 32 static void *doit(void *arg) 33 { 34 int connfd; 35 connfd = *((int *) arg); 36 free(arg); 37 38 Pthread_detach(pthread_self()); 39 str_echo(connfd); /* same function as before */ 40 Close(connfd); 41 return(NULL); 42 }
参考资料
《UNIX网络编程 卷1》