epoll+多進程服務器模型 | C++

多個進程同時監聽一個端口,如果外部有連接,多個進程通過內核實現的競爭機制,就會有一個被喚醒。

直接上代碼:

int main()
{
    // 創建服務器
    int fd = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(9988);
    addr.sin_addr.s_addr = INADDR_ANY;

    int ret = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
    if(ret < 0)
    {
        perror("bind");
        return 1;
    }

    listen(fd, 20);

    int process_count = 20;
    int isParent = 1;
    for(int i=0; i<process_count; ++i)
    {
        pid_t pid = fork();
        if(pid == 0)
        {
            isParent = 0;
            break;
        }
    }

    // 服務器文件描述符被複制了5份
    // 以下代碼被執行6次,每個進程都會執行該代碼
    int epollfd = epoll_create(512);
    
    struct epoll_event ev;
    ev.data.fd = fd;
    ev.events = EPOLLIN;

    // 服務器加入到epoll
    epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev);

    while(1)
    {
        struct epoll_event out_ev[8];
        int ret = epoll_wait(epollfd, out_ev, 8, 2000);

        if(ret > 0)
        {
            for(int i=0; i<ret; ++i)
            {
                struct epoll_event* p = &out_ev[i];
                if(p->data.fd == fd)
                {
                    int newfd = accept(fd, NULL, NULL);
                    ev.data.fd = newfd;
                    epoll_ctl(epollfd, EPOLL_CTL_ADD, newfd, &ev);
                }
                else
                {
                    char buf[1024];
                    int ret = recv(p->data.fd, buf, sizeof(buf), 0);
                    if(ret > 0)
                        printf("%s\n", buf);
                    else // ret <= 0
                    {
                        close(p->data.fd);
                    }
                }
            }
        }
    }

    if(isParent)
    {
        for(int i=0; i<process_count; ++i)
        {
            wait(NULL);
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章