当前位置:  技术问答>linux和unix

一个关于EPOLL的问题,一直没有办法进行解决!请大侠们来帮帮忙啊!

    来源: 互联网  发布时间:2017-02-01

    本文导语:  我编写的epoll的时候发现一个很怪异的问题。 我在windows写编写的客户端程序来链接LINUX下用epoll写的服务端程序。 当进行少量的客户端链接时,客户端发送数据可以被正确的接收到。 当进行大量的客户端链接时(300...

我编写的epoll的时候发现一个很怪异的问题。
我在windows写编写的客户端程序来链接LINUX下用epoll写的服务端程序。
当进行少量的客户端链接时,客户端发送数据可以被正确的接收到。
当进行大量的客户端链接时(300个客户端),客户端发送的数据在epoll接收的时候就会很慢,而且有的时候无法接收完全。
我的实现是这样的。
主进程创建一个wait线程,用来专门等待EPOLL的事件,代码如下:
fds = epoll_wait(lpThreadObj->Parent->m_epollEvents->epoll_fd, lpThreadObj->Parent->m_epollEvents->epoll_events, lpThreadObj->Parent->m_epollEvents->maxfds, 0);
        if (fds m_state)
            {
                sem_post(&lpThreadObj->Wait_exit_sem);
                return NULL;
            }
            continue;
        }
        else
        {
            for(int i = 0; i Parent->m_epollEvents->epoll_events[i].data.ptr;
                if(pClient == NULL) continue;

                if((pClient->Socket == lpThreadObj->Parent->m_ListenClient->Socket) && (pClient->Socket & EPOLLIN))
                {
                    sem_post(&lpThreadObj->Accept_Work_sem);
                    continue;
                }

                if(lpThreadObj->Parent->m_epollEvents->epoll_events[i].events & EPOLLIN)
                {
                    gettimeofday(&pClient->m_ActiveTick, NULL);

                    //加入接收队列中进行等待处理
                    lpThreadObj->addRecvQueue(pClient, OPER_RECEIVE);
                }
                else if(lpThreadObj->Parent->m_epollEvents->epoll_events[i].events & EPOLLOUT)
                {
                    //printf("EPOLLOUT = %d i = %dn", pClient->SocketHandle, i);
                }
            }
       }


sem_post(&lpThreadObj->Accept_Work_sem);会触发一个事件,另外会有一个CEpollAcceptWorkThread线程专门来进行accept
并对每个客户端的链接对象添加监控事件EPOLLIN|EPOLLOUT|EPOLLET。代码如下:
struct epoll_event event;
    event.data.fd = pSocket->Socket;
    event.data.ptr = pSocket;
    event.events = EPOLLIN|EPOLLOUT|EPOLLET;
    int iRet = epoll_ctl(m_epollEvents->epoll_fd, EPOLL_CTL_ADD, pSocket->Socket, &event);
lpThreadObj->addRecvQueue(pClient, OPER_RECEIVE);函数是将读取请求加入到一个待处理队列中。有3个读取线程从此队列获得读取请求,并进行读取。

少量的数据的时候一切都是正常的,当300个链接以上接收数据就和客户端发送的数据量不一致了。

我的环境是:
EPOLL在UBUNTU 11.10系统下开发,UBUNTU 安装在windows下的虚拟机中。
客户端在windows下 



|
肯定是编码问题,注意检查这几个:

1,write和read的返回值是否检查了,因为返回值可能小于请求值或者直接返回-1。
2,你用的ET,编码时是否read/write到发生EAGAIN为止,不读干净就会漏掉数据。、
3,不应该始终注册EPOLLOUT,因为只要网卡不满,永远都会触发EPOLLOUT事件,也就是即便没有任何消息,你的程序都会不停的循环。

|
你讲讲你的服务端架构吧, 就这点代码来看的话是主线程将触发事件的CLIENT放入队列,利用信号量唤醒工作线程,光这么点东西要注意的细节就很多。 

一个CLIENT会不会被多次放入队列中? 如果你没有考虑这个情况, 那么你就肯定没有考虑到同一个CLIENT被不同的线程同时处理的情况。

这种靠线程的架构, 要不就是事件I/O线程读数据拆包,然后交给线程池去处理,之后再通知事件I/O线程发回数据,一个client只能被某一个线程负责,不能一会给这个线程一会给那个线程,这样包序是一个大麻烦,并发也没法处理,你应该理解。

依靠线程的架构说白了就一种,具体一点就是两种。
一种是每个线程负责若干socket的事件监听,这适合CPU多的,非计算的网络通信,主线程只负责accept。
一种是每个线程负责一个socket的处理,适合计算密集的网络通信,主线程还是只负责accept。

你这种写法我看命名就觉得有问题,因为你的主线程肯定不是从accept之后就撒手不管了,而是主线程监听,不停地将client分发到线程,这是不好的。

应该accept之后就将client分发到某个线程,从此改client的死活都由那个线程负责了。
你的问题就是每次client有事件都分发一次,请问如果数据密集了,同一个client在短期内多次来数据,被分发到不同的线程并发处理,请问怎么read怎么send? 毫无办法。

|
你的I/O模型有问题。
三楼说的已经很详细了。

|
可以看看 Unix环境高级编程

|
2,你用的ET,编码时是否read/write到发生EAGAIN为止,不读干净就会漏掉数据。、
3,不应该始终注册EPOLLOUT,因为只要网卡不满,永远都会触发EPOLLOUT事件,也就是即便没有任何消息,你的程序都会不停的循环。

对于2, 实际上处理得当,无需要等到EAGAIN,也不会出现漏掉数据的情况,至少我没出现过。

对于3,ET 不仅对EPOLLIN有效,同样对EPOLLOUT也是有效果的,所以不会出现不停循环的问题,可以看这里
http://www.chineselinuxuniversity.net/patches/18934.shtml 还有ET的描述,是从非出发态突变到触发态,并没说仅针对EPOLLIN事件。

楼主的模型是,一个线程处理epoll,实际读写交由IO线程处理,我觉得可能的问题是同步问题。
我举个例子:
int ret = recv();
if(ret == EAGAIN)
{
   //执行某些处理
   //在这里,套接口有可能又恢复成可读状态
}



    
 
 
 
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • epoll中epoll_event结构体的含义
  • epoll_ctl(,EPOLL_CTL_DEL,); 的问题!!!
  • 第一次用epoll就傻眼,程序报create_epoll error Function not implemented
  • 为Qt添加epoll的高性能I/O复用 qt_eventdispatcher_epoll
  • 请问: 当服务器采用epoll 时,客户端连不上,但若服务器端不用epoll时,也连上并发消息,这是为什么啊
  • epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event)为何老返回-1
  • epoll 退出
  • 关于epoll的几个疑问
  • 大家好,问个问题,关于EPOLL的。。。
  • epoll并发问题
  • 有人碰到过epoll丢信号吗
  • epoll异常问题
  • epoll模型如何限制最大连接数
  • epoll可读的问题
  • python实现Linux异步epoll代码
  • epoll多路复用模型的疑惑,请高手解答
  • epoll,socket超时如何设置?
  • epoll的一个问题
  • 关于epoll的链接库
  • 谁能解释一下epoll、libevent、zeroMQ的区别?


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3