• 【C语言】多进程服务器


    多进程服务器

    步骤

      服务器使用父进程 fork 创建子进程来和客户端进行通信,父进程负责取出连接请求。并且父进程接收子进程退出信号,通过信号处理函数回收子进程
    步骤:
    1.首先屏蔽子进程退出信号
    2.使用socket函数,获取一个socket文件描述符
    3.使用setsockopt端口复用
    4.使用bind函数允许客户端的哪些ip可以访问服务器
    5.使用listen监听客户端连接
    6.使用accept从已连接的客户端队列中取出一个文件描述符,与它通信
    7.使用fork函数创建一个子进程去与上面的文件描述符通信

    代码

    #include "socketwrap.h"
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    // 信号处理函数
    void waitchild(int signo)
    {
        pid_t wpid;
        while (1)
        {
            wpid = waitpid(-1, NULL, WNOHANG);
            if (wpid > 0)
            {
                printf("child exit, wpid==[%d]\n", wpid);
            }
            else if (wpid == 0 || wpid == -1)
            {
                break;
            }
        }
    }
    
    int main()
    {
        // 阻塞SIGCHLD信号
        sigset_t mask;
        sigemptyset(&mask);
        sigaddset(&mask, SIGCHLD);
        sigprocmask(SIG_BLOCK, &mask, NULL);
        int sigbol = 1;
    
        int sfd = Socket(AF_INET, SOCK_STREAM, 0);
    
        // 设置端口复用
        int opt = 1;
        setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
    
        struct sockaddr_in soaddr;
        bzero(&soaddr, sizeof(soaddr));
    
        soaddr.sin_family = AF_INET;
        soaddr.sin_port = htons(9999);
        soaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    
        Bind(sfd, (struct sockaddr *)&soaddr, sizeof(soaddr));
    
        //监听-listen
    	Listen(sfd, 128);
    
        struct sockaddr_in clientsocket;
        socklen_t clilen;
        
        char sIP[16];
    
        while (1)
        {
            clilen = sizeof(clientsocket);
            bzero(&clientsocket, clilen);
            
            int cfd = Accept(sfd, (struct sockaddr *)&clientsocket, &clilen);
    
            /* */
            int pid = fork();
            if (pid == 0)
            {
                // 子进程
                close(sfd);
                char buff[64];
                printf("current pid is [%d],father is [%d]\n", getpid(), getppid());
                while (1)
                {
                    memset(buff, 0x00, sizeof(buff));
                    int n = Read(cfd, buff, sizeof(buff));
                    if (n == 0)
                    {
                        return 0;
                    }
                    else if (n < 0)
                    {
                        perror("child read error");
                        return -1;
                    }
                    printf("child [%d] recv data from [%s:%d]:[%s]\n", getpid(), inet_ntop(AF_INET, &clientsocket.sin_addr.s_addr, sIP, sizeof(sIP)), ntohs(clientsocket.sin_port), buff);
                    for (int i = 0; i < n; i++)
                    {
                        buff[i] = toupper(buff[i]);
                    }
                    n = Write(cfd, buff, n);
                    if (n <= 0)
                    {
                        perror("child write error");
                        return -1;
                    }
                }
            }
            else if (pid > 0)
            {
                // 父进程
                close(cfd);
    
                if (sigbol == 1)
                {
                    sigbol = 0;
                    // 注册SIGCHLD信号处理函数
                    struct sigaction act;
                    act.sa_handler = waitchild;
                    act.sa_flags = 0;
                    sigemptyset(&act.sa_mask);
                    sigaction(SIGCHLD, &act, NULL);
    
                    // 解除对SIGCHLD信号的阻塞
                    sigprocmask(SIG_UNBLOCK, &mask, NULL);
                }
    
                continue;
            }
            else
            {
                perror("fork error");
                close(sfd);
                return -1;
            }
        
            
        }
    
        return 0;
    }
    
  • 相关阅读:
    SpringMVC Day 10 : 拦截器
    港股第四家“造车新势力“,零跑汽车通过IPO聆讯
    PIE-Engine APP:凉山州火灾高发地异常度分析系统
    bp神经网络数据预测实例,bp网络神经预测模型
    文字表达细化的提示词的学习笔记
    机器学习-分类器-总结
    MySQL数据库下载与安装使用
    使用OpenVINO实现人体动作识别
    力扣(LeetCode)84. 柱状图中最大的矩形 (C++)
    快速了解服务器单CPU与双CPU
  • 原文地址:https://blog.csdn.net/qq_44653106/article/details/140386530