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
答案 0 :(得分:2)
它看着插座,如果有的话 在一定时间内没有信号 然后它返回0以关闭套接字。
为什么?
我以为我需要这个代码来检测 意外的用户断开连接或数据 腐败(客户端发送100个字节但是 服务器收到90个字节然后 服务器将等待最后10个字节 哪个不会到达。
你没有。您将获得另一个读取事件,其中读取将返回0表示EOS或错误事件。
如果要实现非活动超时,则必须在主选择循环中实现 。也就是说,跟踪每个套接字的最后活动时间,如果它太长则关闭套接字或做任何你必须做的事情。在迭代并再次调用select()之前,将此测试放在select()循环的底部。
目前,每个读取事件都会阻止超时持续时间内的所有其他select()事件。所以整个服务器都被阻止了。