epoll使用详解

</pre><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">在linux的网络编程中,很长的时间都在使用select来做事件触发。在linux新的内核中,有了一种替换它的机制,就是epoll。</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">相比于select,epoll最大的好处在于它不会随着监听fd数目的增长而降低效率。因为在内核中的select实现中,它是采用轮询来处理的,轮询的fd数目越多,自然耗时越多。并且,在linux/posix_types.h头文件有这样的声明:</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">#define __FD_SETSIZE    1024</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">表示select最多同时监听1024个fd,当然,可以通过修改头文件再重编译内核来扩大这个数目,但这似乎并不治本。</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">epoll的接口非常简单,一共就三个函数:</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">1. int epoll_create(int size);</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">创建一个epoll的句柄,size用来告诉内核这个监听的数目一共有多大。这个参数不同于select()中的第一个参数,给出最大监听的fd+1的值。需要注意的是,当创建好epoll句柄后,它就是会占用一个fd值,在linux下如果查看/proc/进程id/fd/,是能够看到这个fd的,所以在使用完epoll后,必须调用close()关闭,否则可能导致fd被耗尽。</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">epoll的事件注册函数,它不同与select()是在监听事件时告诉内核要监听什么类型的事件,而是在这里先注册要监听的事件类型。第一个参数是epoll_create()的返回值,第二个参数表示动作,用三个宏来表示:</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">EPOLL_CTL_ADD:注册新的fd到epfd中;</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">EPOLL_CTL_MOD:修改已经注册的fd的监听事件;</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">EPOLL_CTL_DEL:从epfd中删除一个fd;</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">第三个参数是需要监听的fd,第四个参数是告诉内核需要监听什么事,struct epoll_event结构如下:</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">typedef union epoll_data {</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">    void *ptr;</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">    int fd;</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">    __uint32_t u32;</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">    __uint64_t u64;</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">} epoll_data_t;</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">struct epoll_event {</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">    __uint32_t events; /* Epoll events */</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">    epoll_data_t data; /* User data variable */</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">};</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">events可以是以下几个宏的集合:</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">EPOLLOUT:表示对应的文件描述符可以写;</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">EPOLLERR:表示对应的文件描述符发生错误;</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">EPOLLHUP:表示对应的文件描述符被挂断;</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">3. int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">等待事件的产生,类似于select()调用。参数events用来从内核得到事件的集合,maxevents告之内核这个events有多大,这个 maxevents的值不能大于创建epoll_create()时的size,参数timeout是超时时间(毫秒,0会立即返回,-1将不确定,也有说法说是永久阻塞)。该函数返回需要处理的事件数目,如返回0表示已超时。</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">4、关于ET、LT两种工作模式:</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">可以得出这样的结论:</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">ET模式仅当状态发生变化的时候才获得通知,这里所谓的状态的变化并不包括缓冲区中还有未处理的数据,也就是说,如果要采用ET模式,需要一直read/write直到出错为止,很多人反映为什么采用ET模式只接收了一部分数据就再也得不到通知了,大多因为这样;而LT模式是只要有数据没有处理就会一直通知下去的.</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">那么究竟如何来使用epoll呢?其实非常简单。</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">通过在包含一个头文件#include <sys/epoll.h> 以及几个简单的API将可以大大的提高你的网络服务器的支持人数。</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">首先通过create_epoll(int maxfds)来创建一个epoll的句柄,其中maxfds为你epoll所支持的最大句柄数。这个函数会返回一个新的epoll句柄,之后的所有操作将通过这个句柄来进行操作。在用完之后,记得用close()来关闭这个创建出来的epoll句柄。</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">之后在你的网络主循环里面,每一帧的调用epoll_wait(int epfd, epoll_event events, int max events, int timeout)来查询所有的网络接口,看哪一个可以读,哪一个可以写了。基本的语法为:</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">nfds = epoll_wait(kdpfd, events, maxevents, -1);</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">其中kdpfd为用epoll_create创建之后的句柄,events是一个epoll_event*的指针,当epoll_wait这个函数操作成功之后,epoll_events里面将储存所有的读写事件。max_events是当前需要监听的所有socket句柄数。最后一个timeout是 epoll_wait的超时,为0的时候表示马上返回,为-1的时候表示一直等下去,直到有事件范围,为任意正整数的时候表示等这么长的时间,如果一直没有事件,则范围。一般如果网络主循环是单独的线程的话,可以用-1来等,这样可以保证一些效率,如果是和主逻辑在同一个线程的话,则可以用0来保证主循环的效率。</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">epoll_wait范围之后应该是一个循环,遍利所有的事件。</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">几乎所有的epoll程序都使用下面的框架:</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">    for( ; ; )</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">    {</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">        nfds = epoll_wait(epfd,events,20,500);</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">        for(i=0;i<nfds;++i)</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">        {</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">            if(events[i].data.fd==listenfd) //有新的连接</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">            {</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">                connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen); //accept这个连接</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">                ev.data.fd=connfd;</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">                ev.events=EPOLLIN|EPOLLET;</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">                epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev); //将新的fd添加到epoll的监听队列中</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">            }</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">            else if( events[i].events&EPOLLIN ) //接收到数据,读socket</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">            {</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">                n = read(sockfd, line, MAXLINE)) < 0    //读</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">                ev.data.ptr = md;     //md为自定义类型,添加数据</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">                ev.events=EPOLLOUT|EPOLLET;</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">                epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);//修改标识符,等待下一个循环时发送数据,异步处理的精髓</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">            }</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">            else if(events[i].events&EPOLLOUT) //有数据待发送,写socket</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">            {</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">                struct myepoll_data* md = (myepoll_data*)events[i].data.ptr;    //取数据</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">                sockfd = md->fd;</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">                send( sockfd, md->ptr, strlen((char*)md->ptr), 0 );        //发送数据</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">                ev.data.fd=sockfd;</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">                ev.events=EPOLLIN|EPOLLET;</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">                epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); //修改标识符,等待下一个循环时接收数据</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">            }</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">            else</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">            {</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">                //其他的处理</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">            }</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">        }</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">    }</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">下面给出一个完整的服务器端例子:</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><table border="1" cellspacing="0" cellpadding="0" bgcolor="#f1f1f1" bordercolor="#999999" style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px; width: 643px; border-collapse: collapse;"><tbody><tr><td><p style="line-height: 21px; margin: 5px;"><code><span style="color: rgb(0, 0, 0);"><span style="color: rgb(0, 0, 204);">#</span><span style="color: rgb(255, 0, 0);">include</span> <span style="color: rgb(0, 0, 204);"><</span><span style="color: rgb(255, 0, 0);">iostream</span><span style="color: rgb(0, 0, 204);">></span><span style="color: rgb(0, 0, 204);">#</span><span style="color: rgb(255, 0, 0);">include</span> <span style="color: rgb(0, 0, 204);"><</span>sys<span style="color: rgb(0, 0, 204);">/</span><span style="color: rgb(255, 0, 0);">socket</span><span style="color: rgb(0, 0, 204);">.</span>h<span style="color: rgb(0, 0, 204);">></span><span style="color: rgb(0, 0, 204);">#</span><span style="color: rgb(255, 0, 0);">include</span> <span style="color: rgb(0, 0, 204);"><</span>sys<span style="color: rgb(0, 0, 204);">/</span>epoll<span style="color: rgb(0, 0, 204);">.</span>h<span style="color: rgb(0, 0, 204);">></span><span style="color: rgb(0, 0, 204);">#</span><span style="color: rgb(255, 0, 0);">include</span> <span style="color: rgb(0, 0, 204);"><</span>netinet<span style="color: rgb(0, 0, 204);">/</span>in<span style="color: rgb(0, 0, 204);">.</span>h<span style="color: rgb(0, 0, 204);">></span><span style="color: rgb(0, 0, 204);">#</span><span style="color: rgb(255, 0, 0);">include</span> <span style="color: rgb(0, 0, 204);"><</span>arpa<span style="color: rgb(0, 0, 204);">/</span>inet<span style="color: rgb(0, 0, 204);">.</span>h<span style="color: rgb(0, 0, 204);">></span><span style="color: rgb(0, 0, 204);">#</span><span style="color: rgb(255, 0, 0);">include</span> <span style="color: rgb(0, 0, 204);"><</span>fcntl<span style="color: rgb(0, 0, 204);">.</span>h<span style="color: rgb(0, 0, 204);">></span><span style="color: rgb(0, 0, 204);">#</span><span style="color: rgb(255, 0, 0);">include</span> <span style="color: rgb(0, 0, 204);"><</span>unistd<span style="color: rgb(0, 0, 204);">.</span>h<span style="color: rgb(0, 0, 204);">></span><span style="color: rgb(0, 0, 204);">#</span><span style="color: rgb(255, 0, 0);">include</span> <span style="color: rgb(0, 0, 204);"><</span>stdio<span style="color: rgb(0, 0, 204);">.</span>h<span style="color: rgb(0, 0, 204);">></span><span style="color: rgb(0, 0, 204);">#</span><span style="color: rgb(255, 0, 0);">include</span> <span style="color: rgb(0, 0, 204);"><</span><span style="color: rgb(255, 0, 0);">errno</span><span style="color: rgb(0, 0, 204);">.</span>h<span style="color: rgb(0, 0, 204);">></span><span style="color: rgb(0, 0, 255);">using</span> <span style="color: rgb(0, 0, 255);">namespace</span> <span style="color: rgb(255, 0, 0);">std</span><span style="color: rgb(0, 0, 204);">;</span><span style="color: rgb(0, 0, 204);">#</span><span style="color: rgb(255, 0, 0);">define</span> MAXLINE 5<span style="color: rgb(0, 0, 204);">#</span><span style="color: rgb(255, 0, 0);">define</span> OPEN_MAX 100<span style="color: rgb(0, 0, 204);">#</span><span style="color: rgb(255, 0, 0);">define</span> LISTENQ 20<span style="color: rgb(0, 0, 204);">#</span><span style="color: rgb(255, 0, 0);">define</span> SERV_PORT 5000<span style="color: rgb(0, 0, 204);">#</span><span style="color: rgb(255, 0, 0);">define</span> INFTIM 1000<span style="color: rgb(0, 0, 255);">void</span> setnonblocking<span style="color: rgb(0, 0, 204);">(</span><span style="color: rgb(0, 0, 255);">int</span> sock<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">{</span>    <span style="color: rgb(0, 0, 255);">int</span> opts<span style="color: rgb(0, 0, 204);">;</span>    opts<span style="color: rgb(0, 0, 204);">=</span>fcntl<span style="color: rgb(0, 0, 204);">(</span>sock<span style="color: rgb(0, 0, 204);">,</span>F_GETFL<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>    <span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 204);">(</span>opts<span style="color: rgb(0, 0, 204);"><</span>0<span style="color: rgb(0, 0, 204);">)</span>    <span style="color: rgb(0, 0, 204);">{</span>        <span style="color: rgb(255, 0, 0);">perror</span><span style="color: rgb(0, 0, 204);">(</span><span style="color: rgb(255, 0, 255);">"fcntl(sock,GETFL)"</span><span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>        <span style="color: rgb(255, 0, 0);">exit</span><span style="color: rgb(0, 0, 204);">(</span>1<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>    <span style="color: rgb(0, 0, 204);">}</span>    opts <span style="color: rgb(0, 0, 204);">=</span> opts<span style="color: rgb(0, 0, 204);">|</span>O_NONBLOCK<span style="color: rgb(0, 0, 204);">;</span>    <span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 204);">(</span>fcntl<span style="color: rgb(0, 0, 204);">(</span>sock<span style="color: rgb(0, 0, 204);">,</span>F_SETFL<span style="color: rgb(0, 0, 204);">,</span>opts<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);"><</span>0<span style="color: rgb(0, 0, 204);">)</span>    <span style="color: rgb(0, 0, 204);">{</span>        <span style="color: rgb(255, 0, 0);">perror</span><span style="color: rgb(0, 0, 204);">(</span><span style="color: rgb(255, 0, 255);">"fcntl(sock,SETFL,opts)"</span><span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>        <span style="color: rgb(255, 0, 0);">exit</span><span style="color: rgb(0, 0, 204);">(</span>1<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>    <span style="color: rgb(0, 0, 204);">}</span><span style="color: rgb(0, 0, 204);">}</span><span style="color: rgb(0, 0, 255);">int</span> main<span style="color: rgb(0, 0, 204);">(</span><span style="color: rgb(0, 0, 255);">int</span> argc<span style="color: rgb(0, 0, 204);">,</span> <span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 204);">*</span> argv<span style="color: rgb(0, 0, 204);">[</span><span style="color: rgb(0, 0, 204);">]</span><span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">{</span>    <span style="color: rgb(0, 0, 255);">int</span> i<span style="color: rgb(0, 0, 204);">,</span> maxi<span style="color: rgb(0, 0, 204);">,</span> listenfd<span style="color: rgb(0, 0, 204);">,</span> connfd<span style="color: rgb(0, 0, 204);">,</span> sockfd<span style="color: rgb(0, 0, 204);">,</span>epfd<span style="color: rgb(0, 0, 204);">,</span>nfds<span style="color: rgb(0, 0, 204);">,</span> portnumber<span style="color: rgb(0, 0, 204);">;</span>    ssize_t n<span style="color: rgb(0, 0, 204);">;</span>    <span style="color: rgb(0, 0, 255);">char</span> <span style="color: rgb(255, 0, 0);">line</span><span style="color: rgb(0, 0, 204);">[</span>MAXLINE<span style="color: rgb(0, 0, 204);">]</span><span style="color: rgb(0, 0, 204);">;</span>    <span style="color: rgb(255, 0, 0);">socklen_t</span> clilen<span style="color: rgb(0, 0, 204);">;</span>    <span style="color: rgb(0, 0, 255);">if</span> <span style="color: rgb(0, 0, 204);">(</span> 2 <span style="color: rgb(0, 0, 204);">=</span><span style="color: rgb(0, 0, 204);">=</span> argc <span style="color: rgb(0, 0, 204);">)</span>    <span style="color: rgb(0, 0, 204);">{</span>        <span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 204);">(</span> <span style="color: rgb(0, 0, 204);">(</span>portnumber <span style="color: rgb(0, 0, 204);">=</span> <span style="color: rgb(255, 0, 0);">atoi</span><span style="color: rgb(0, 0, 204);">(</span>argv<span style="color: rgb(0, 0, 204);">[</span>1<span style="color: rgb(0, 0, 204);">]</span><span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">)</span> <span style="color: rgb(0, 0, 204);"><</span> 0 <span style="color: rgb(0, 0, 204);">)</span>        <span style="color: rgb(0, 0, 204);">{</span>            <span style="color: rgb(255, 0, 0);">fprintf</span><span style="color: rgb(0, 0, 204);">(</span><span style="color: rgb(255, 0, 0);">stderr</span><span style="color: rgb(0, 0, 204);">,</span><span style="color: rgb(255, 0, 255);">"Usage:%s portnumber/a/n"</span><span style="color: rgb(0, 0, 204);">,</span>argv<span style="color: rgb(0, 0, 204);">[</span>0<span style="color: rgb(0, 0, 204);">]</span><span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>            <span style="color: rgb(0, 0, 255);">return</span> 1<span style="color: rgb(0, 0, 204);">;</span>        <span style="color: rgb(0, 0, 204);">}</span>    <span style="color: rgb(0, 0, 204);">}</span>    <span style="color: rgb(0, 0, 255);">else</span>    <span style="color: rgb(0, 0, 204);">{</span>        <span style="color: rgb(255, 0, 0);">fprintf</span><span style="color: rgb(0, 0, 204);">(</span><span style="color: rgb(255, 0, 0);">stderr</span><span style="color: rgb(0, 0, 204);">,</span><span style="color: rgb(255, 0, 255);">"Usage:%s portnumber/a/n"</span><span style="color: rgb(0, 0, 204);">,</span>argv<span style="color: rgb(0, 0, 204);">[</span>0<span style="color: rgb(0, 0, 204);">]</span><span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>        <span style="color: rgb(0, 0, 255);">return</span> 1<span style="color: rgb(0, 0, 204);">;</span>    <span style="color: rgb(0, 0, 204);">}</span>    <span style="color: rgb(255, 153, 0);">//声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件</span>    <span style="color: rgb(0, 0, 255);">struct</span> epoll_event ev<span style="color: rgb(0, 0, 204);">,</span>events<span style="color: rgb(0, 0, 204);">[</span>20<span style="color: rgb(0, 0, 204);">]</span><span style="color: rgb(0, 0, 204);">;</span>    <span style="color: rgb(255, 153, 0);">//生成用于处理accept的epoll专用的文件描述符</span>    epfd<span style="color: rgb(0, 0, 204);">=</span>epoll_create<span style="color: rgb(0, 0, 204);">(</span>256<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>    <span style="color: rgb(0, 0, 255);">struct</span> <span style="color: rgb(255, 0, 0);">sockaddr_in</span> clientaddr<span style="color: rgb(0, 0, 204);">;</span>    <span style="color: rgb(0, 0, 255);">struct</span> <span style="color: rgb(255, 0, 0);">sockaddr_in</span> serveraddr<span style="color: rgb(0, 0, 204);">;</span>    listenfd <span style="color: rgb(0, 0, 204);">=</span> <span style="color: rgb(255, 0, 0);">socket</span><span style="color: rgb(0, 0, 204);">(</span><span style="color: rgb(255, 0, 0);">AF_INET</span><span style="color: rgb(0, 0, 204);">,</span> <span style="color: rgb(255, 0, 0);">SOCK_STREAM</span><span style="color: rgb(0, 0, 204);">,</span> 0<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>    <span style="color: rgb(255, 153, 0);">//把socket设置为非阻塞方式</span>    <span style="color: rgb(255, 153, 0);">//setnonblocking(listenfd);</span>    <span style="color: rgb(255, 153, 0);">//设置与要处理的事件相关的文件描述符</span>    ev<span style="color: rgb(0, 0, 204);">.</span>data<span style="color: rgb(0, 0, 204);">.</span>fd<span style="color: rgb(0, 0, 204);">=</span>listenfd<span style="color: rgb(0, 0, 204);">;</span>    <span style="color: rgb(255, 153, 0);">//设置要处理的事件类型</span>    ev<span style="color: rgb(0, 0, 204);">.</span>events<span style="color: rgb(0, 0, 204);">=</span>EPOLLIN<span style="color: rgb(0, 0, 204);">|</span>EPOLLET<span style="color: rgb(0, 0, 204);">;</span>    <span style="color: rgb(255, 153, 0);">//ev.events=EPOLLIN;</span>    <span style="color: rgb(255, 153, 0);">//注册epoll事件</span>    epoll_ctl<span style="color: rgb(0, 0, 204);">(</span>epfd<span style="color: rgb(0, 0, 204);">,</span>EPOLL_CTL_ADD<span style="color: rgb(0, 0, 204);">,</span>listenfd<span style="color: rgb(0, 0, 204);">,</span><span style="color: rgb(0, 0, 204);">&</span>ev<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>    bzero<span style="color: rgb(0, 0, 204);">(</span><span style="color: rgb(0, 0, 204);">&</span>serveraddr<span style="color: rgb(0, 0, 204);">,</span> <span style="color: rgb(0, 0, 255);">sizeof</span><span style="color: rgb(0, 0, 204);">(</span>serveraddr<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>    serveraddr<span style="color: rgb(0, 0, 204);">.</span>sin_family <span style="color: rgb(0, 0, 204);">=</span> <span style="color: rgb(255, 0, 0);">AF_INET</span><span style="color: rgb(0, 0, 204);">;</span>    <span style="color: rgb(0, 0, 255);">char</span> <span style="color: rgb(0, 0, 204);">*</span>local_addr<span style="color: rgb(0, 0, 204);">=</span><span style="color: rgb(255, 0, 255);">"127.0.0.1"</span><span style="color: rgb(0, 0, 204);">;</span>    inet_aton<span style="color: rgb(0, 0, 204);">(</span>local_addr<span style="color: rgb(0, 0, 204);">,</span><span style="color: rgb(0, 0, 204);">&</span><span style="color: rgb(0, 0, 204);">(</span>serveraddr<span style="color: rgb(0, 0, 204);">.</span>sin_addr<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span><span style="color: rgb(255, 153, 0);">//htons(portnumber);</span>    serveraddr<span style="color: rgb(0, 0, 204);">.</span>sin_port<span style="color: rgb(0, 0, 204);">=</span><span style="color: rgb(255, 0, 0);">htons</span><span style="color: rgb(0, 0, 204);">(</span>portnumber<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>    <span style="color: rgb(255, 0, 0);">bind</span><span style="color: rgb(0, 0, 204);">(</span>listenfd<span style="color: rgb(0, 0, 204);">,</span><span style="color: rgb(0, 0, 204);">(</span><span style="color: rgb(255, 0, 0);">sockaddr</span> <span style="color: rgb(0, 0, 204);">*</span><span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">&</span>serveraddr<span style="color: rgb(0, 0, 204);">,</span> <span style="color: rgb(0, 0, 255);">sizeof</span><span style="color: rgb(0, 0, 204);">(</span>serveraddr<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>    <span style="color: rgb(255, 0, 0);">listen</span><span style="color: rgb(0, 0, 204);">(</span>listenfd<span style="color: rgb(0, 0, 204);">,</span> LISTENQ<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>    maxi <span style="color: rgb(0, 0, 204);">=</span> 0<span style="color: rgb(0, 0, 204);">;</span>    <span style="color: rgb(0, 0, 255);">for</span> <span style="color: rgb(0, 0, 204);">(</span> <span style="color: rgb(0, 0, 204);">;</span> <span style="color: rgb(0, 0, 204);">;</span> <span style="color: rgb(0, 0, 204);">)</span> <span style="color: rgb(0, 0, 204);">{</span>        <span style="color: rgb(255, 153, 0);">//等待epoll事件的发生</span>        nfds<span style="color: rgb(0, 0, 204);">=</span>epoll_wait<span style="color: rgb(0, 0, 204);">(</span>epfd<span style="color: rgb(0, 0, 204);">,</span>events<span style="color: rgb(0, 0, 204);">,</span>20<span style="color: rgb(0, 0, 204);">,</span>500<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>        <span style="color: rgb(255, 153, 0);">//处理所发生的所有事件</span>        <span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 204);">(</span>i<span style="color: rgb(0, 0, 204);">=</span>0<span style="color: rgb(0, 0, 204);">;</span>i<span style="color: rgb(0, 0, 204);"><</span>nfds<span style="color: rgb(0, 0, 204);">;</span><span style="color: rgb(0, 0, 204);">+</span><span style="color: rgb(0, 0, 204);">+</span>i<span style="color: rgb(0, 0, 204);">)</span>        <span style="color: rgb(0, 0, 204);">{</span>            <span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 204);">(</span>events<span style="color: rgb(0, 0, 204);">[</span>i<span style="color: rgb(0, 0, 204);">]</span><span style="color: rgb(0, 0, 204);">.</span>data<span style="color: rgb(0, 0, 204);">.</span>fd<span style="color: rgb(0, 0, 204);">=</span><span style="color: rgb(0, 0, 204);">=</span>listenfd<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(255, 153, 0);">//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口,建立新的连接。</span>            <span style="color: rgb(0, 0, 204);">{</span>                connfd <span style="color: rgb(0, 0, 204);">=</span> <span style="color: rgb(255, 0, 0);">accept</span><span style="color: rgb(0, 0, 204);">(</span>listenfd<span style="color: rgb(0, 0, 204);">,</span><span style="color: rgb(0, 0, 204);">(</span><span style="color: rgb(255, 0, 0);">sockaddr</span> <span style="color: rgb(0, 0, 204);">*</span><span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">&</span>clientaddr<span style="color: rgb(0, 0, 204);">,</span> <span style="color: rgb(0, 0, 204);">&</span>clilen<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>                <span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 204);">(</span>connfd<span style="color: rgb(0, 0, 204);"><</span>0<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">{</span>                    <span style="color: rgb(255, 0, 0);">perror</span><span style="color: rgb(0, 0, 204);">(</span><span style="color: rgb(255, 0, 255);">"connfd<0"</span><span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>                    <span style="color: rgb(255, 0, 0);">exit</span><span style="color: rgb(0, 0, 204);">(</span>1<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>                <span style="color: rgb(0, 0, 204);">}</span>                <span style="color: rgb(255, 153, 0);">//setnonblocking(connfd);</span>                <span style="color: rgb(0, 0, 255);">char</span> <span style="color: rgb(0, 0, 204);">*</span>str <span style="color: rgb(0, 0, 204);">=</span> inet_ntoa<span style="color: rgb(0, 0, 204);">(</span>clientaddr<span style="color: rgb(0, 0, 204);">.</span>sin_addr<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>                <span style="color: rgb(255, 0, 0);">cout</span> <span style="color: rgb(0, 0, 204);"><</span><span style="color: rgb(0, 0, 204);"><</span> <span style="color: rgb(255, 0, 255);">"accapt a connection from "</span> <span style="color: rgb(0, 0, 204);"><</span><span style="color: rgb(0, 0, 204);"><</span> str <span style="color: rgb(0, 0, 204);"><</span><span style="color: rgb(0, 0, 204);"><</span> <span style="color: rgb(255, 0, 0);">endl</span><span style="color: rgb(0, 0, 204);">;</span>                <span style="color: rgb(255, 153, 0);">//设置用于读操作的文件描述符</span>                ev<span style="color: rgb(0, 0, 204);">.</span>data<span style="color: rgb(0, 0, 204);">.</span>fd<span style="color: rgb(0, 0, 204);">=</span>connfd<span style="color: rgb(0, 0, 204);">;</span>                <span style="color: rgb(255, 153, 0);">//设置用于注测的读操作事件</span>                ev<span style="color: rgb(0, 0, 204);">.</span>events<span style="color: rgb(0, 0, 204);">=</span>EPOLLIN<span style="color: rgb(0, 0, 204);">|</span>EPOLLET<span style="color: rgb(0, 0, 204);">;</span>                <span style="color: rgb(255, 153, 0);">//ev.events=EPOLLIN;</span>                <span style="color: rgb(255, 153, 0);">//注册ev</span>                epoll_ctl<span style="color: rgb(0, 0, 204);">(</span>epfd<span style="color: rgb(0, 0, 204);">,</span>EPOLL_CTL_ADD<span style="color: rgb(0, 0, 204);">,</span>connfd<span style="color: rgb(0, 0, 204);">,</span><span style="color: rgb(0, 0, 204);">&</span>ev<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>            <span style="color: rgb(0, 0, 204);">}</span>            <span style="color: rgb(0, 0, 255);">else</span> <span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 204);">(</span>events<span style="color: rgb(0, 0, 204);">[</span>i<span style="color: rgb(0, 0, 204);">]</span><span style="color: rgb(0, 0, 204);">.</span>events<span style="color: rgb(0, 0, 204);">&</span>EPOLLIN<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(255, 153, 0);">//如果是已经连接的用户,并且收到数据,那么进行读入。</span>            <span style="color: rgb(0, 0, 204);">{</span>                <span style="color: rgb(255, 0, 0);">cout</span> <span style="color: rgb(0, 0, 204);"><</span><span style="color: rgb(0, 0, 204);"><</span> <span style="color: rgb(255, 0, 255);">"EPOLLIN"</span> <span style="color: rgb(0, 0, 204);"><</span><span style="color: rgb(0, 0, 204);"><</span> <span style="color: rgb(255, 0, 0);">endl</span><span style="color: rgb(0, 0, 204);">;</span>                <span style="color: rgb(0, 0, 255);">if</span> <span style="color: rgb(0, 0, 204);">(</span> <span style="color: rgb(0, 0, 204);">(</span>sockfd <span style="color: rgb(0, 0, 204);">=</span> events<span style="color: rgb(0, 0, 204);">[</span>i<span style="color: rgb(0, 0, 204);">]</span><span style="color: rgb(0, 0, 204);">.</span>data<span style="color: rgb(0, 0, 204);">.</span>fd<span style="color: rgb(0, 0, 204);">)</span> <span style="color: rgb(0, 0, 204);"><</span> 0<span style="color: rgb(0, 0, 204);">)</span>                    <span style="color: rgb(0, 0, 255);">continue</span><span style="color: rgb(0, 0, 204);">;</span>                <span style="color: rgb(0, 0, 255);">if</span> <span style="color: rgb(0, 0, 204);">(</span> <span style="color: rgb(0, 0, 204);">(</span>n <span style="color: rgb(0, 0, 204);">=</span> <span style="color: rgb(255, 0, 0);">read</span><span style="color: rgb(0, 0, 204);">(</span>sockfd<span style="color: rgb(0, 0, 204);">,</span> <span style="color: rgb(255, 0, 0);">line</span><span style="color: rgb(0, 0, 204);">,</span> MAXLINE<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">)</span> <span style="color: rgb(0, 0, 204);"><</span> 0<span style="color: rgb(0, 0, 204);">)</span> <span style="color: rgb(0, 0, 204);">{</span>                    <span style="color: rgb(0, 0, 255);">if</span> <span style="color: rgb(0, 0, 204);">(</span><span style="color: rgb(255, 0, 0);">errno</span> <span style="color: rgb(0, 0, 204);">=</span><span style="color: rgb(0, 0, 204);">=</span> ECONNRESET<span style="color: rgb(0, 0, 204);">)</span> <span style="color: rgb(0, 0, 204);">{</span>                        <span style="color: rgb(255, 0, 0);">close</span><span style="color: rgb(0, 0, 204);">(</span>sockfd<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>                        events<span style="color: rgb(0, 0, 204);">[</span>i<span style="color: rgb(0, 0, 204);">]</span><span style="color: rgb(0, 0, 204);">.</span>data<span style="color: rgb(0, 0, 204);">.</span>fd <span style="color: rgb(0, 0, 204);">=</span> <span style="color: rgb(0, 0, 204);">-</span>1<span style="color: rgb(0, 0, 204);">;</span>                    <span style="color: rgb(0, 0, 204);">}</span> <span style="color: rgb(0, 0, 255);">else</span>                        <span style="color: rgb(255, 0, 0);">std</span><span style="color: rgb(0, 0, 204);">:</span><span style="color: rgb(0, 0, 204);">:</span><span style="color: rgb(255, 0, 0);">cout</span><span style="color: rgb(0, 0, 204);"><</span><span style="color: rgb(0, 0, 204);"><</span><span style="color: rgb(255, 0, 255);">"readline error"</span><span style="color: rgb(0, 0, 204);"><</span><span style="color: rgb(0, 0, 204);"><</span><span style="color: rgb(255, 0, 0);">std</span><span style="color: rgb(0, 0, 204);">:</span><span style="color: rgb(0, 0, 204);">:</span><span style="color: rgb(255, 0, 0);">endl</span><span style="color: rgb(0, 0, 204);">;</span>                <span style="color: rgb(0, 0, 204);">}</span> <span style="color: rgb(0, 0, 255);">else</span> <span style="color: rgb(0, 0, 255);">if</span> <span style="color: rgb(0, 0, 204);">(</span>n <span style="color: rgb(0, 0, 204);">=</span><span style="color: rgb(0, 0, 204);">=</span> 0<span style="color: rgb(0, 0, 204);">)</span> <span style="color: rgb(0, 0, 204);">{</span>                    <span style="color: rgb(255, 0, 0);">close</span><span style="color: rgb(0, 0, 204);">(</span>sockfd<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>                    events<span style="color: rgb(0, 0, 204);">[</span>i<span style="color: rgb(0, 0, 204);">]</span><span style="color: rgb(0, 0, 204);">.</span>data<span style="color: rgb(0, 0, 204);">.</span>fd <span style="color: rgb(0, 0, 204);">=</span> <span style="color: rgb(0, 0, 204);">-</span>1<span style="color: rgb(0, 0, 204);">;</span>                <span style="color: rgb(0, 0, 204);">}</span>                <span style="color: rgb(255, 0, 0);">line</span><span style="color: rgb(0, 0, 204);">[</span>n<span style="color: rgb(0, 0, 204);">]</span> <span style="color: rgb(0, 0, 204);">=</span> <span style="color: rgb(255, 0, 255);">'/0'</span><span style="color: rgb(0, 0, 204);">;</span>                <span style="color: rgb(255, 0, 0);">cout</span> <span style="color: rgb(0, 0, 204);"><</span><span style="color: rgb(0, 0, 204);"><</span> <span style="color: rgb(255, 0, 255);">"read "</span> <span style="color: rgb(0, 0, 204);"><</span><span style="color: rgb(0, 0, 204);"><</span> <span style="color: rgb(255, 0, 0);">line</span> <span style="color: rgb(0, 0, 204);"><</span><span style="color: rgb(0, 0, 204);"><</span> <span style="color: rgb(255, 0, 0);">endl</span><span style="color: rgb(0, 0, 204);">;</span>                <span style="color: rgb(255, 153, 0);">//设置用于写操作的文件描述符</span>                ev<span style="color: rgb(0, 0, 204);">.</span>data<span style="color: rgb(0, 0, 204);">.</span>fd<span style="color: rgb(0, 0, 204);">=</span>sockfd<span style="color: rgb(0, 0, 204);">;</span>                <span style="color: rgb(255, 153, 0);">//设置用于注测的写操作事件</span>                ev<span style="color: rgb(0, 0, 204);">.</span>events<span style="color: rgb(0, 0, 204);">=</span>EPOLLOUT<span style="color: rgb(0, 0, 204);">|</span>EPOLLET<span style="color: rgb(0, 0, 204);">;</span>                <span style="color: rgb(255, 153, 0);">//修改sockfd上要处理的事件为EPOLLOUT</span>                <span style="color: rgb(255, 153, 0);">//epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);</span>            <span style="color: rgb(0, 0, 204);">}</span>            <span style="color: rgb(0, 0, 255);">else</span> <span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 204);">(</span>events<span style="color: rgb(0, 0, 204);">[</span>i<span style="color: rgb(0, 0, 204);">]</span><span style="color: rgb(0, 0, 204);">.</span>events<span style="color: rgb(0, 0, 204);">&</span>EPOLLOUT<span style="color: rgb(0, 0, 204);">)</span> <span style="color: rgb(255, 153, 0);">// 如果有数据发送</span>            <span style="color: rgb(0, 0, 204);">{</span>                sockfd <span style="color: rgb(0, 0, 204);">=</span> events<span style="color: rgb(0, 0, 204);">[</span>i<span style="color: rgb(0, 0, 204);">]</span><span style="color: rgb(0, 0, 204);">.</span>data<span style="color: rgb(0, 0, 204);">.</span>fd<span style="color: rgb(0, 0, 204);">;</span>                <span style="color: rgb(255, 0, 0);">write</span><span style="color: rgb(0, 0, 204);">(</span>sockfd<span style="color: rgb(0, 0, 204);">,</span> <span style="color: rgb(255, 0, 0);">line</span><span style="color: rgb(0, 0, 204);">,</span> n<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>                <span style="color: rgb(255, 153, 0);">//设置用于读操作的文件描述符</span>                ev<span style="color: rgb(0, 0, 204);">.</span>data<span style="color: rgb(0, 0, 204);">.</span>fd<span style="color: rgb(0, 0, 204);">=</span>sockfd<span style="color: rgb(0, 0, 204);">;</span>                <span style="color: rgb(255, 153, 0);">//设置用于注测的读操作事件</span>                ev<span style="color: rgb(0, 0, 204);">.</span>events<span style="color: rgb(0, 0, 204);">=</span>EPOLLIN<span style="color: rgb(0, 0, 204);">|</span>EPOLLET<span style="color: rgb(0, 0, 204);">;</span>                <span style="color: rgb(255, 153, 0);">//修改sockfd上要处理的事件为EPOLIN</span>                epoll_ctl<span style="color: rgb(0, 0, 204);">(</span>epfd<span style="color: rgb(0, 0, 204);">,</span>EPOLL_CTL_MOD<span style="color: rgb(0, 0, 204);">,</span>sockfd<span style="color: rgb(0, 0, 204);">,</span><span style="color: rgb(0, 0, 204);">&</span>ev<span style="color: rgb(0, 0, 204);">)</span><span style="color: rgb(0, 0, 204);">;</span>            <span style="color: rgb(0, 0, 204);">}</span>        <span style="color: rgb(0, 0, 204);">}</span>    <span style="color: rgb(0, 0, 204);">}</span>    <span style="color: rgb(0, 0, 255);">return</span> 0<span style="color: rgb(0, 0, 204);">;</span><span style="color: rgb(0, 0, 204);">}</span></span></code></p></td></tr></tbody></table><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><p></p><p><span style="font-family:Arial;color:#333333;"><span style="font-size: 14px; line-height: 26px;">原文:<a target=_blank href="http://blog.csdn.net/ljx0305/article/details/4065058">http://blog.csdn.net/ljx0305/article/details/4065058</a></span></span></p><pre code_snippet_id="502907" snippet_file_name="blog_20141031_5_4000118" name="code" class="cpp">
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值