POSIX 线程(Pthread)
之前的 TCP 回射服务器通过 fork 子进程来维护多用户的请求, 但是首先 fork 需要将完整的父进程内存映像复制到子进程, 并需要复制所有描述符, 开销大; 其次, 子进程难以和父进程通信. 故而可以尝试多线程编程方式, 线程开销小, 且可以很轻易的通过全局变量通信(线程共享全局变量, 但是局部变量(占空间)各自独享), 但是需要线程并发, 全局变量读写冲突.
下面是多线程式的 TCP 服务器 str_cli 部分, 其余的握手连接部分可以参照 TCP 回射服务器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
#include "unpthread.h" void *copyto(void *); static int sockfd; /* global for both threads to access */ static FILE *fp; void str_cli(FILE *fp_arg, int sockfd_arg) { char recvline[MAXLINE]; pthread_t tid; // 数据复制到全局, 方便线程使用 sockfd = sockfd_arg; fp = fp_arg; Pthread_create(&tid, NULL, copyto, NULL); while (Readline(sockfd, recvline, MAXLINE) > 0) Fputs(recvline, stdout); } void * copyto(void *arg) { char sendline[MAXLINE]; while (Fgets(sendline, MAXLINE, fp) != NULL) Writen(sockfd, sendline, strlen(sendline)); Shutdown(sockfd, SHUT_WR); /* 完全关闭套接字读写 */ return(NULL); // 数据处理完毕, 终止线程 } |
上述示例需要引入线程的头文件 unpthread.h
, 而后声明线程函数 copyto(void *), 当客户端建立连接, 收发消息时, 程序调用 str_cli
函数, 本函数不服务客户端, 而是通过 Pthread_create
创建一个线程 copyto
来维护客户端的数据交互, 真正的数据回射最终由 copyto 函数处理.