• C++ 异步 IO(二) 服务器端多进程


    通过多线程或多进程可以减弱阻塞IO的负面作用。

    /* For sockaddr_in */
    #include <netinet/in.h>
    /* For socket functions */
    #include <sys/socket.h>
    
    #include <unistd.h>
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAX_LINE 16384
    
    char
    rot13_char(char c)
    {
        /* We don't want to use isalpha here; setting the locale would change
         * which characters are considered alphabetical. */
        if ((c >= 'a' && c <= 'm') || (c >= 'A' && c <= 'M'))
            return c + 13;
        else if ((c >= 'n' && c <= 'z') || (c >= 'N' && c <= 'Z'))
            return c - 13;
        else
            return c;
    }
    
    void
    child(int fd)
    {
        char outbuf[MAX_LINE+1];
        size_t outbuf_used = 0;
        ssize_t result;
    
        while (1) {
            char ch;
            result = recv(fd, &ch, 1, 0);
            if (result == 0) {
                break;
            } else if (result == -1) {
                perror("read");
                break;
            }
    
            /* We do this test to keep the user from overflowing the buffer. */
            if (outbuf_used < sizeof(outbuf)) {
                outbuf[outbuf_used++] = rot13_char(ch);
            }
    
            if (ch == '
    ') {
                send(fd, outbuf, outbuf_used, 0);
                outbuf_used = 0;
                continue;
            }
        }
    }
    
    void
    run(void)
    {
        int listener;
        struct sockaddr_in sin;
    
        sin.sin_family = AF_INET;
        sin.sin_addr.s_addr = 0;
        sin.sin_port = htons(40713);
    
        listener = socket(AF_INET, SOCK_STREAM, 0);
    
    #ifndef WIN32
        {
            int one = 1;
            setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
        }
    #endif
    
        if (bind(listener, (struct sockaddr*)&sin, sizeof(sin)) < 0) {
            perror("bind");
            return;
        }
    
        if (listen(listener, 16)<0) {
            perror("listen");
            return;
        }
    
    
    
        while (1) {
            struct sockaddr_storage ss;
            socklen_t slen = sizeof(ss);
            int fd = accept(listener, (struct sockaddr*)&ss, &slen);
            if (fd < 0) {
                perror("accept");
            } else {
                if (fork() == 0) {
                    child(fd);
                    exit(0);
                }
            }
        }
    }
    
    int
    main(int c, char **v)
    {
        run();
        return 0;
    }

    1. 函数 rot13_char(char) 是用来转换字符的,{A,a}~{M,m} -> {N,n}~{Z,z} 其余符号不变

    2. server监听端口并响应连接

      2.1 listener = socket(AF_INET, SOCKET_STREAM, 0) 创建套接字

      2.2 bind(listener, (sockaddr*)&sin, size(sin)) 绑定套接字到端口

      2.3 listen(listener, 16) 开始监听

      2.4 struct sockaddr_storage ss;

          socklen_t slen = sizeof(ss);

          int fd = accept(listener, (struct sockaddr*)&ss, &slen);

        每个fd标识响应的一个请求

      2.5 if (fork() == 0) { child(fd); exit(0);}

        创建一个子进程,响应一个请求     

    3. server端子进程的处理函数

      3.1 void child(int fd) 处理函数接口

      3.2 result = recv(fd, &ch, 1, 0); 从client端读取一个字符

             send(fd, outbuf, outbuf_used, 0); 发送一个字符串到client端

    1. 创建子进程的过程

        pid_t pid;
    
         switch (pid = fork())
         {
         case -1:
    
             perror("The fork failed!";
             break;
         case 0:
             printf("I'm a child!";
             system("touch /home/tom/abc.txt";
             _exit(0);
    
         default:
             printf("Child's pid is %d
    ",pid);
         }

    程序会输出default的内容,并且创建 abc.txt

    原因是:创建子进程时,子进程复制了父进程的内容。子进程和父进程同时进入switch语句,但父子进程的pid并不同,因此进入不同的case。

  • 相关阅读:
    httpclient妙用一 httpclient作为客户端调用soap webservice(转)
    WebService学习总结(转)
    C++的override和final
    C++类const和static成员初始化
    C++数据存储方式
    C++类成员存储大小
    内联函数
    C++接口的概念
    C++深拷贝和浅拷贝
    C++构造函数以及何时被调用
  • 原文地址:https://www.cnblogs.com/zhouzhuo/p/3778617.html
Copyright © 2020-2023  润新知