0
while(m_severRun){

    printf("ServerManager::eventAcceptLoop, epoll_wait\n");
    int event_cnt = epoll_wait(m_epfd, m_events, EPOLL_SIZE, -1);
    if(event_cnt == -1){
        perror("epoll_wait error \n");
        break;
    }

    for(int i=0; i<event_cnt; i++){

        SocketClient *conn = reinterpret_cast<SocketClient *>(m_events[i].data.ptr);


        if(conn->getFd() == m_serverSocket->getFd()){

            printf("ServerManager::eventAcceptLoop, A Client has been connected \n");

            struct sockaddr_in clnt_adr;
            socklen_t adr_sz = sizeof(clnt_adr);
            int clnt_sock = accept(m_serverSocket->getFd(), (struct sockaddr*)&clnt_adr, &adr_sz);

            SocketClient* client = new SocketClient(clnt_sock);
            if(!addClient(client))
                break;
        }
        else{

            if(m_events[i].events & EPOLLRDHUP){
                printf("ServerManager::eventAcceptLoop, EPOLLRDHUP \n");
                removeClient(conn);
                close(conn->getFd());
                continue;
            }

            if(m_events[i].events & EPOLLIN){

                printf("ServerManager::eventAcceptLoop, EPOLLIN \n");
                int recv = conn->recv();

                if(recv <= 0){
                    removeClient(conn);
                    close(conn->getFd());
                }
                else{
                    printf("ServerManager::eventAcceptLoop, A message has been received \n");
                    vector<char> data = conn->getData();
                    addWork(conn, data);
                }
            }

            if(m_events[i].events & EPOLLERR)
                printf("ServerManager::eventAcceptLoop, EPOLLERR \n");
        }
    }//for loop end
}//while loop end

我正在研究网络编程(tcp)并且我有这个代码。这是我第一次使用 epoll,所以我不确定这个设计是否正确。此外,我正在使用一个线程池(5 个子线程),每当我从 epoll 读取数据时,我都会将其放入线程池的队列中。问题是在读取功能中我可以看到瓶颈问题。

在 read 函数中,它调用 ObserveSocket

int SocketClient::ObserveSock(int sock, int timeout){

    printf("SocketClient::ObserveSock called\n");

    fd_set reads;
    int fd_max;
    struct timeval _timeout;

    FD_ZERO(&reads);
    FD_SET(sock, &reads);
    fd_max = sock + 1;

    _timeout.tv_sec = timeout;
    _timeout.tv_usec = 0;

    return select(fd_max, &reads, 0, 0, &_timeout);
}

它监视套接字,如果在一定时间内没有信号,则返回 0 以关闭套接字。我想我需要这段代码来检测意外的用户断开连接或数据损坏(客户端发送了 100 个字节,但服务器收到了 90 个字节,然后服务器将等待最后 10 个字节不会到达)。

如果你们能告诉我如何解决瓶颈问题和任何架构问题,我将不胜感激。

我还将寻找使用 epoll 并详细介绍异常处理的任何好的教程。

提前致谢。

编辑

在 recv() 函数内部,它只调用 read 函数,在我阅读之前,我调用 ObserveSocket

4

1 回答 1

2

它监视套接字,如果在一定时间内没有信号,则返回 0 以关闭套接字。

为什么?

我想我需要这段代码来检测意外的用户断开连接或数据损坏(客户端发送了 100 个字节,但服务器收到了 90 个字节,然后服务器将等待最后 10 个字节不会到达)。

你没有。您将收到另一个读取事件,其中读取将返回 0 指示 EOS,或错误事件。

如果要实现不活动超时,则必须在主选择循环中实现它。也就是说,跟踪每个套接字的最后活动时间,如果它变得太长,请关闭套接字或做任何你必须做的事情。将此测试放在 select() 循环的底部,在您迭代并再次调用 select() 之前。

目前,每个读取事件都会在超时时间内阻塞所有其他 select() 事件。因此,您的整个服务器都被阻止了。

于 2011-06-23T04:27:57.397 回答