fork()
创建子进程处理客户端请求,父进程继续监听端口,子进程处理完请求后退出,实现并发处理。
C多进程服务器是一种在网络编程中常用的并发模型,用于处理多个客户端的连接请求,以下是关于C多进程服务器的详细解释:
1、基本原理:
C多进程服务器通过创建多个子进程来处理客户端请求,每个子进程是操作系统中独立运行的单位,拥有自己的内存空间和资源。
当有新的客户端连接请求到达时,服务器创建一个新的子进程来处理该请求,子进程负责与客户端通信并提供所需的服务。
2、实现步骤:
屏蔽信号:需要屏蔽子进程退出信号(如SIGCHLD),以避免父进程被意外终止。
创建套接字:使用socket函数创建一个套接字文件描述符,用于监听客户端的连接请求。
设置套接字选项:通过setsockopt函数设置套接字选项,如端口复用等。
绑定地址:使用bind函数将套接字绑定到指定的IP地址和端口号上,允许客户端访问服务器。
监听连接:使用listen函数使套接字进入被动打开状态,准备接受客户端的连接请求。
接受连接:使用accept函数从已连接的客户端队列中取出一个文件描述符,与它通信。
创建子进程:对于每一个客户端连接请求,父进程通过fork函数创建一个子进程去与客户端通信。
3、优缺点:
优点:稳定性高,由于每个子进程都是相互独立的,一个子进程的崩溃或错误不会影响其他子进程的执行,这种独立性使得多进程并发服务器能够有效地隔离错误,提高服务器的可靠性。
缺点:创建和管理多个进程需要消耗更多的系统资源,包括内存和CPU时间,进程间的通信也需要特殊的机制,例如管道或共享内存,以便在不同进程之间传递数据,由于每个进程都有自己的内存空间,进程间的数据共享和同步可能会变得复杂。
4、示例代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <signal.h> #include <sys/wait.h> void sigchld_handler(int signo) { while (waitpid(-1, NULL, WNOHANG) > 0); } int main() { int listenfd = socket(AF_INET, SOCK_STREAM, 0); if (listenfd == -1) { perror("socket error"); exit(1); } struct sockaddr_in serveraddr; memset(&serveraddr, 0, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons(9999); if (bind(listenfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1) { perror("bind error"); close(listenfd); exit(1); } if (listen(listenfd, 128) == -1) { perror("listen error"); close(listenfd); exit(1); } struct sigaction sa; sa.sa_handler = sigchld_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGCHLD, &sa, NULL); while (1) { int connfd = accept(listenfd, NULL, NULL); if (connfd == -1) { perror("accept error"); continue; } pid_t pid = fork(); if (pid == 0) { // Child process close(listenfd); char buff[64]; while (1) { memset(buff, 0x00, sizeof(buff)); int n = read(connfd, buff, sizeof(buff)); if (n <= 0) break; for (int i = 0; i < n; i++) { buff[i] = toupper(buff[i]); } write(connfd, buff, n); } close(connfd); exit(0); } else if (pid > 0) { // Parent process close(connfd); } else { // Fork failed perror("fork error"); close(connfd); } } }
FAQs:
1、问:为什么需要使用多进程服务器而不是单线程或单进程服务器?
答:多进程服务器可以提高系统的资源利用率和程序的运行效率,同时可以更有效地隔离错误,提高服务器的可靠性,每个子进程都是相互独立的,一个子进程的崩溃或错误不会影响其他子进程的执行。
2、问:多进程服务器中的父子进程是如何通信的?
答:在多进程服务器中,父子进程之间的通信通常通过管道、共享内存或消息队列等机制进行,由于每个进程都有自己的内存空间,进程间的数据共享和同步可能会变得复杂。