TCP并发服务器(一)——每个客户一个子进程

TCP并发服务器(一)——每个客户一个子进程

1.说明

这是最传统的并发服务器,对于每一个客户请求fork一个子进程。问题在于每次fork一个子进程比较耗费时间,下面会讲预创建进程。

程序代码基于UNP的库。

程序在使用进程的模式下是最慢的。

 

2.代码

#include "unp.h"

int main(int argc, char *argv[])
{
    int listenfd;
    socklen_t addrlen;
    if (argc = 2) {
        listenfd = Tcp_listen(NULL, argv[1], &addrlen);
    } else if (argc ==3) {
        listenfd = Tcp_listen(argv[1], argv[2], &addrlen);
    } else {
        err_quit("Usage: a.out [ <host> ] <port#>");
    }
    struct sockaddr *cliaddr = (struct sockaddr*)Malloc(addrlen);

    void sig_chld(int), sig_int(int), web_child(int);
    Signal(SIGCHLD, sig_chld);
    Signal(SIGINT, sig_int);

    for ( ; ;) {
        socklen_t clilen = addrlen;    
        DPRINTF("Wait for a connection
");
        int connfd = accept(listenfd, cliaddr, &clilen);    //clilen用于值-结果参数,可能会改变,所以每次重新赋值,所以此处不能使用addrlen
        DPRINTF("Accept a connection
");
        if (connfd < 0) {
            if (errno == EINTR) {
                continue;
            } else {
                err_sys("accept() error");
            }
        } 

        pid_t childpid = Fork();
        if (childpid == 0) {        //child process
            DPRINTF("Fork a child process
");
            Close(listenfd);        //close listening socket
            web_child(connfd);        //process request
            exit(0);
        }
        Close(connfd);                //parent closes connected socket
    } //end for(;;)

    return 0;
}

void sig_int(int)
{
    DPRINTF("sig_int()
");
    void pr_cpu_time(void);
    pr_cpu_time();
    exit(0);
}

void sig_chld(int)
{
    static int cnt = 0;
    pid_t pid;
    int stat;
    //param1: 想要等待的PID;-1: 等待第一个终止的子进程
    //param2: 子进程的终止状态(整数)
    //param3: 附加选项;WNOHANG:没有子进程终止时,不阻塞
    while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) {    //成功:返回进程ID > 0, 出错:0或-1
        DPRINTF("Waitpid for %d child process
", ++cnt);
        ;
    }

    return;
}

  

原文地址:https://www.cnblogs.com/hancm/p/3864179.html