本文共 2628 字,大约阅读时间需要 8 分钟。
做网络服务的时候并发服务端程序的编写必不可少。前端客户端应用程序是否稳定一部分取决于客户端自身,而更多的取决于服务器是否相应时间够迅速,够稳定.
常见的linux并发服务器模型;
多进程并发服务器
多线程并发服务器
select多路I/O转接服务器
poll多路I/O转接服务器
epool多路I/O转接服务器.
本次主要讨论多线程并发服务器模型:
使用多线程模型开发服务时需要考虑以下问题
1. 调整进程内最大文件描述符上限.
2. 线程如有共享数据, 考虑线程同步.
3. 服务于客户端线程退出时, 退出处理(退出值, works线程处于分离态)
4. 系统负载, 随着链接客户的增加, 导致其它线程不能级时得到CPU
.server代码[实际开发中要特别注意函数调用返回值判断]
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <ctype.h> #include <arpa/inet.h> #include <sys/socket.h> #include <sys/types.h> #include <pthread.h> /* * 多线程并发服务器 * author sea time 2016/06/20 */ #define SERV_PORT 9096 //服务所占用端口 #define SERV_ADDR "10.10.101.105" //服务所占用ip //线程处理函数 void * thread_handler( void * args){ char buf[BUFSIZ]; //BUFSIZ 内置宏 8192 int n, i; int fd = ( int )args; //转换获得客户端描述符 while (1){ bzero(buf, sizeof (buf)); n = read(fd, buf, sizeof (buf)); //对方已关闭 if (0 == n){ //关闭连接 close(fd); printf ( "close...\n" ); break ; } else if (0 < n){ //大小写转换 for (i = 0; i < n; i++){ buf[i] = toupper (buf[i]); } //发送给客户端 write(fd, buf, n); } } pthread_exit(NULL); } int main( int argc, char * argv[]){ pthread_t tid; int listenfd, connfd; struct sockaddr_in serv_addr, clie_addr; socklen_t clie_addr_len; int opt; char str[INET_ADDRSTRLEN]; //INET_ADDRSTRLEN 内存宏 16 //创建监听套接字 //AF_INET: ipv4 //SOCK_STREAM tcp流类型 //IPPROTO_TCP tcp协议 listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //设置端口复用 opt = 1; setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)); //初始化为0 bzero(&serv_addr, sizeof (serv_addr)); //指定族: ipv4 serv_addr.sin_family = AF_INET; //指定端口号并转换成网络字节序 serv_addr.sin_port = htons(SERV_PORT); //指定ip并转换为网络字节序 inet_pton(AF_INET, SERV_ADDR, &serv_addr.sin_addr.s_addr); //绑定到监听套接字 bind(listenfd, ( struct sockaddr*)&serv_addr, sizeof (serv_addr)); //设置同时连接请求上限 listen(listenfd, SOMAXCONN); while (1){ clie_addr_len = sizeof (clie_addr); //阻塞获取连接 connfd = accept(listenfd, ( struct sockaddr*)&clie_addr, &clie_addr_len); //输出连接的客户端信息 printf ( "%s:%d connect successfully!\n" , inet_ntop(AF_INET, &clie_addr.sin_addr.s_addr, str, sizeof (str)), ntohs(clie_addr.sin_port)); //创建线程与之连接处理, 并将描述符给works线程 pthread_create(&tid, NULL, thread_handler, ( void *)connfd); //设置线程分离 pthread_detach(tid); } close(listenfd); return 0; } |
多线程与多于在linux当中CPU调试对待一样, 所以在连接数不多的请况下使用多线程和多进程非常方便.
本文转自asd1123509133 51CTO博客,原文链接:http://blog.51cto.com/lisea/1791023,如需转载请自行联系原作者