Linux TCP 服务器编程(二):简单的并发服务器
来源:互联网 发布:python 数组 clear 编辑:程序博客网 时间:2024/04/29 17:10
【版权声明:转载请保留出处:blog.csdn.net/gentleliu。邮箱:shallnew*163.com】
在讲述并发服务器之前,需要先了解一下fork函数。
#include<unistd.h> pid_t fork(void);
该函数很特殊,调用一次返回2次:在父进程中返回一次,返回的是子进程的ID号;在子进程中再返回一次,返回值为0;
父进程中打开的所有描述符在fork之后与子进程分享,一般父进程调用accept函数之后就调用fork函数,连接的套接字和子进程共享。通常情况下,父进程关闭连接套接字,子进程继续读写该套接字。Linux编写并发服务器最简单的方法就是使用fork一个子进程来服务每个客户。
下面修改前一章给出的服务器,得出一个简单的并发服务器。
#include <stdio.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <stdlib.h> #include <arpa/inet.h> #include <netinet/in.h> #include "server.h" #include "ly_debug.h" void accept_handle(int connfd, struct sockaddr_in peeraddr); int main(int argc, const char *argv[]) { int sockfd, connfd; struct sockaddr_in seraddr, peeraddr; socklen_t addrlen; COMPILE_TIME_PRINT; if (argc != 2) { printf("Usage: %s <port>\n", argv[0]); return -1; } sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { LY_ERR("socket: %s\n", strerror(errno)); return -1; } seraddr.sin_family = AF_INET; seraddr.sin_port = ntohs(atoi(argv[1])); seraddr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(sockfd, (struct sockaddr *)&seraddr, sizeof(struct sockaddr))) { LY_ERR("bind: %s\n", strerror(errno)); return -1; } if (listen(sockfd, MAX_CONN) < 0) { LY_ERR("listen: %s\n", strerror(errno)); return -1; } addrlen = sizeof(struct sockaddr); for (;;) { connfd = accept(sockfd, (struct sockaddr *)(&peeraddr), &addrlen); if (connfd < 0) { LY_ERR("accept: %s\n", strerror(errno)); continue; } if (0 == fork()) { close(sockfd); accept_handle(connfd, peeraddr); close(connfd); exit(0); } close(connfd); } return 0; } void accept_handle(int connfd, struct sockaddr_in peeraddr) { char buf[32] = "Hello, welcome to server!"; LY_IFO("Receive request from %s, port %d\n", inet_ntop(AF_INET, &peeraddr.sin_addr, buf, sizeof(buf)), ntohs(peeraddr.sin_port)); sleep(10); snprintf(buf, sizeof(buf), "Hello, welcome to server!"); if (send(connfd, buf, sizeof(buf), 0) < 0) { LY_ERR("send: %s\n", strerror(errno)); return; } }如上一节同样的方式运行,只用一个客户端连接服务器和上一节执行结果没有什么区别,但是如果使用多个客户端连接服务器就不一样了。如果使用2个或多个客户端几乎同时连接服务器的话,服务器大约10秒就可以处理完客户请求并返回信息,上一节的迭代服务器处理时间会随着客户端的连接数量成倍数的增加。
如果在多个客户连接且服务器处理完成之后,读者使用ps查看进程时会发现有很多的僵尸进程,其实那些都是服务器父进程产生处理客户请求的子进程,子进程调用exit退出之后发送SIGCHLD信号给父进程,在此服务器程序之中父进程没有处理该信号,该信号默认是被忽略,这样子进程就进入了僵死状态。如下图,服务器在处理了3个客户请求后出现了三个服务器进程状态为Z+。
我们必须清理僵死进程,否则会随着客户连接的增多耗尽系统资源,这涉及到信号处理,在下一章我们将讲解服务器对信号的处理,解决该问题。
0 0
- Linux TCP 服务器编程(二):简单的并发服务器
- TCP套接字编程实现简单的并发服务器
- Linux TCP 服务器编程(六):基于线程的并发服务器
- Linux网络编程——tcp并发服务器(多线程)
- Linux网络编程——tcp并发服务器(多线程)
- Linux网络编程——tcp并发服务器(多线程)
- Linux系统编程(35)—— socket编程之TCP服务器的并发处理
- linux TCP 服务器编程(一):简单的迭代服务器
- TCP并发服务器模型(二)
- Linux网络编程之简单并发服务器
- Linux网络编程之简单并发服务器
- Linux网络编程之简单并发服务器
- Windows下的网络编程(tcp循环并发服务器)
- Linux网络编程 - TCP Socket 简单练习:线程池实现并发服务器
- 简单建立基于Linux建立并发TCP服务器
- Linux select TCP并发服务器与客户端编程
- Linux select TCP并发服务器与客户端编程
- socket编程之简单的TCP服务器
- 10194 - Football (aka Soccer)
- 串的模式匹配KMP算法模板
- Understand to relation between zoomImage and actualImage
- 使用NPOI操作Excel文件及其日期处理
- OpenCV程序内存泄露的预防与检测
- Linux TCP 服务器编程(二):简单的并发服务器
- Amdahl
- C++ 模板与泛型编程学习笔记01
- linux 提取RPM包文件(共7项技巧)
- 黑马程序员_程序的三种结构+枚举
- 1119 Factstone Benchmark
- 火龙果具有润肠、滑肠作用
- RTNETLINK answers: File exists错误解决方法
- CVS checkout on windows ANT Build: invalid CEN header (bad signature)