C++网络编程I/O 多路复用之epoll(二)

编程入门 行业动态 更新时间:2024-10-19 08:47:33

C++网络编程I/O <a href=https://www.elefans.com/category/jswz/34/1768459.html style=多路复用之epoll(二)"/>

C++网络编程I/O 多路复用之epoll(二)

前言

开始我觉得网络编程很难,连socket是什么都不知道,套接字什么鬼翻译,仿佛这成了横在我学习路上的巨石,难以逾越,不敢上手。人总需要下一个决心,感谢好自理每集带给我的持续的动力,哇,有一种我正在走有人走过的路的安全感。但是在把头硬扎进去学习完之后,回过头看,发现那巨石仅仅是一颗小石头,又觉得自己学会网络编程也没什么了不起啊,往深的网络编程知识还有很多,不仅仅是linux api,还有底层网络原理。
似乎总是这样,从来没有什么轻而易举做成的事情,但做完之后又觉得这是一件轻而易举的事情,前方的路充满了巨石阻碍前进,人生或许就是这样,不断地打怪升级,将大石头变成小石头,走出一条清晰地路。

回顾上文

上节讲了epoll的发展,相关函数和触发方式。

补充EPOLLONESHOT事件

与 poll 的事件宏相比,epoll 新增了两个事件宏 EPOLLET和EPOLLONESHOT,EPOLLET就是边沿触发模式,我用过了,但是EPOLLONESHOT还没有用过。我这里写的也是看原理的理解,其应用是在epoll+多线程配合使用场景,我们想一下,如果在处理socket数据的时候,该socket又有新数据可读,有新的读事件会触发(ET),那么会有新线程去处理该事件。出现了两个线程同时处理一个fd的情况,而我们期望一个fd在任何时候都只被一个线程处理。
我们可以通过注册EPOLLONESHOT事件来解决上述问题,对于注册了EPOLLONESHOT事件的fd,操作系统最多触发其上注册的一个可读/可写/异常事件,且只触发一次,这样,一个线程在处理某个fd时,另一个线程是不可能有机会操作该fd的;同时,当fd上的事件被某个线程处理完之后,需要立即重置EPOLLONESHOT事件,确保下一次有事件发生时,能够被触发,让其他线程有机会处理该fd。

阻塞 IO

在套接字缓冲区没准备好的情况下,会一直等待
LT 模式下,由于只要有数据就会触发读事件,所以可以触发一次读一次,不一次读完,不会有问题,但是在 ET 模式下,由于在新的数据到来之前,尽管有数据就绪,也不会触发读事件,因此会导致有未读完的数据,所以为了保证能够读取到完整的数据包,需要使用 while(1) 之类的循环去读,一直读,读到没有,最后一次 read 阻塞,就一直等待着,无法退出,因为所有的数据都已经读完了。

非阻塞 IO

在套接字缓冲区没准备好时,会立即返回
在 LT 模式下,使用非阻塞 IO 的效果与阻塞 IO 差不多,在 ET 模式下,处理的逻辑与上面类似,但是由于使用的 非阻塞 IO ,因此不会导致最后一次 read 阻塞,而是会返回 EAGAIN ,通过errno的错误码判断退出。

代码思路

  1. 初始化套接字:lfd = socket();bind();listen();
  2. 初始化epoll:int epfd = epoll_create(); //设置红黑树结点
  3. 创建监听事件数组:struct epoll_event tmp, ep[1024]; //tmp:用来设置单个fd属性 ep:epoll_wait函数返回值
  4. 将lfd挂载到红黑树:tmp.events = EPOLLIN;tmp.data.fd = lfd;epoll_ctl(epfd, EPOLL_CTL_ADD, lfd, &tmp);
  5. 循环监听
    while(1) {ret = epoll_wait(epfd, ep, 1024, -1);    //实时监听for(i = 0; i < ret; i++) {if(ep[i].data.fd == lfd) {    //lfd满足读事件,有新的客户端要发生连接请求cfd = accept();tmp.events = EPOLLIN;     //初始化cfd的监听属性emp.data.fd = cfd;epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &tmp);    //将cfd挂载到树上} else if {    //cfd发生数据请求int n = read(ep[i].data.fd, buf, sizeof(buf));if( n == 0 ) {close(ep[i].data.fd);epoll_ctl(epfd, EPOLL_CTL_DEL, ep[i].data.fd, NULL);} else if( n > 0) {//数据交换}}
    }
    

总结

最后再谈一谈吧,epoll不是单独使用,学习到了epoll在是开始,后面还有线程池,反应堆模型,协议解析,数据库等等一大堆的内容,尽管这样做出来的东西在企业看来仍然是小儿科,就问你难受不难受。冲冲冲!!!

更多推荐

C++网络编程I/O 多路复用之epoll(二)

本文发布于:2024-03-04 19:51:42,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1710253.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:多路   复用   网络编程   epoll

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!