epoll架构问题与瓶颈问题
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
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
I am working on a network programming(tcp) and I have this code. This is my first time using epoll so I am not sure this design is correct. Also, I am using a thread pool (5 child threads) and whenever I read data from epoll I put that on the queue in the thread pool. The problem is that in the read function I can see the bottle neck problem.
In the read function, it calls 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);
}
It watches the socket and if there is no signal for a certain amount of time then it returns 0 to close the socket. I thought I need this code to detect unexpected user disconnection or data corruption (client sent 100 bytes but server received 90 bytes then the server will wait for the last 10 bytes which won't arrive).
I will be very appreciated if you guys can tell me how I can fix the bottle neck problem and any architecture issues on this.
I will also look for any good tutorial that using epoll and covers exception handling in detail.
Thanks in advance.
EDIT
Inside of recv() function it just calls read function and before I read I call the ObserveSocket
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
为什么?
你不知道。您将收到另一个读取事件,其中读取将返回 0 指示 EOS,或者错误事件。
如果您想实现不活动超时,则必须在主选择循环中实现它。也就是说,跟踪每个套接字的最后活动时间,如果时间太长,则关闭套接字或执行任何您必须执行的操作。在再次迭代并调用 select() 之前,将此测试放在 select() 循环的底部。
目前,每个读取事件都会在超时时间内阻塞所有其他 select() 事件。所以你的整个服务器都被封锁了。
Why?
You don't. You will get another read event where the read will return 0 indicating EOS, or an error event.
If you want to implement an inactivity timeout you have to implement it in the main select loop. That is, keep track of the last activity time for each socket, and if it gets too long close the socket or do whatever you have to do. Put this testing at the bottom of the select() loop, before you iterate and call select() again.
At the moment every read event is blocking all other select() events for the timeout duration. So your entire server is blocked.