select 和 epoll的编程实现区别(2)
来源:互联网 发布:linux压缩文件夹zip 编辑:程序博客网 时间:2024/05/19 02:44
原文:http://blog.csdn.net/huangdh79/article/details/5739037
网上已有很多关于这两个函数的效率问题的文章,在这里不再累述。
本文主要对两个函数的编程细节问题,进行分析。
epoll使用et模式。select使用非阻塞模式
共用代码
1。设置句柄为非阻塞方式
- int setnonblocking(int sockfd)
- {
- if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1)
- return -1;
- return 0;
- }
2。创建监听句柄并打开监听
- int create_listen_fd(void)
- {
- #define SERV_PORT 9999
- int listenfd;
- struct sockaddr_in servaddr;
- listenfd = socket(AF_INET, SOCK_STREAM, 0);
- if(listenfd == -1)
- return -1;
- memset(&servaddr, 0x00, sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- servaddr.sin_port = htons(SERV_PORT);
- if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1)
- return -1;
- if(listen(listenfd, 5) == -1)
- return -1;
- return listenfd;
- }
测试场景
1。客户端发送数据后等待,服务器端不对到达数据进行读取。
目的:测试如果有事件到达,但处理结束后管道内仍然有数据存留,各种i/o复用模式是否仍对此事件作出相应。
结果:
1)epoll在数据到达后被唤醒,处理完业务流程后(不对socket管道内数据进行读取),又被阻塞到epoll_wait上。
- int main(int argc, char** argv)
- {
- int epfd, nfds;
- //声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件
- struct epoll_event ev,events[20];
- int listenfd, connfd;
- char buf[100];
- if((listenfd = create_listen_fd()) == -1)
- {
- printf("create_listen_fd error/n");
- return -1;
- }
- if(setnonblocking(listenfd) == -1)
- {
- printf("set non block error/n");
- return -1;
- }
- //创建一个epoll的句柄,size用来告诉内核这个监听的数目一共有多大。
- epfd = epoll_create(256);
- //设置与要处理的事件相关的文件描述符
- ev.data.fd = listenfd;
- //设置要处理的事件类型,当描述符可读时出发,出发方式为ET模式
- ev.events = EPOLLIN | EPOLLET;
- //注册epoll事件
- epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev);
- for(;;)
- {
- //等待epoll事件的发生
- nfds = epoll_wait(epfd, events, 20, -1);
- printf("up/n");
- for(int i = 0; i < nfds; i++)
- {
- if(events[i].data.fd==listenfd)
- {
- connfd = accept(listenfd, NULL, NULL);
- setnonblocking(connfd);
- //设置用于读操作的文件描述符
- ev.data.fd = connfd;
- //设置用于注测的读操作事件
- ev.events = EPOLLIN | EPOLLET;
- //注册ev
- epoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &ev);
- }
- else if(events[i].events & EPOLLIN)
- {
- if ( (connfd = events[i].data.fd) < 0) continue;
- //sleep(10);
- while(false)
- {
- memset(buf, 0x00, 100);
- int rn;
- if((rn = read(connfd, buf, 10)) < 0)
- {
- if(errno == EAGAIN)
- {
- printf("read finish break/n");
- break;
- }
- }
- else if(rn == 0)
- {
- close(connfd);
- epoll_ctl(epfd, EPOLL_CTL_DEL, connfd, NULL);
- printf("close /n");
- break;
- }
- printf("read buf %s/n", buf);
- }
- }
- }
- }
- return 0;
- }
2)select在数据到达后被唤醒,处理完业务流程后(不对socket管道内数据进行读取),select会再次被唤醒。
- int main(int argc, char** argv)
- {
- #define HANDLE_CONNFD_COUNT 100
- int connfdSet[HANDLE_CONNFD_COUNT];
- fd_set rset,allset;
- int listenfd, connfd;
- int nfds;
- int iMax;
- char buf[100];
- for(int i = 0; i < HANDLE_CONNFD_COUNT; i++)
- {
- connfdSet[i] = -1;
- }
- if((listenfd = create_listen_fd()) == -1)
- {
- printf("create_listen_fd error/n");
- return -1;
- }
- setnonblocking(listenfd);
- FD_ZERO(&rset);
- FD_SET(listenfd, &rset);
- FD_ZERO(&allset);
- allset = rset;
- iMax = listenfd;
- for(;;)
- {
- rset = allset;
- nfds = select(iMax + 1, &rset, NULL, NULL, NULL);
- printf("up/n");
- if(FD_ISSET(listenfd, &rset))
- {
- connfd = accept(listenfd, NULL, NULL);
- setnonblocking(connfd);
- FD_SET(connfd, &allset);
- if(connfd > iMax)
- iMax = connfd;
- for(int i = 0; i < HANDLE_CONNFD_COUNT; i++)
- {
- if(connfdSet[i] < 0)
- connfdSet[i] = connfd;
- break;
- }
- if(--nfds == 0)
- continue;
- }
- else
- {
- for(int i = 0; i < HANDLE_CONNFD_COUNT; i++)
- {
- if(connfdSet[i] < 0)
- continue;
- if(FD_ISSET(connfdSet[i], &rset))
- {
- memset(buf, 0x00, sizeof(buf));
- //read(connfdSet[i], buf, 100);
- printf("read buf:%s/n", buf);
- if(--nfds == 0)
- break;
- }
- }
- }
- }
- return 0;
- }
0
上一篇:select 和 epoll的编程实现区别
下一篇:linux非阻塞式socket编程之select()用法
相关热门文章
- test123
- 编写安全代码——小心有符号数...
- 使用openssl api进行加密解密...
- 一段自己打印自己的c程序...
- sql relay的c++接口
- linux dhcp peizhi roc
- 关于Unix文件的软链接
- 求教这个命令什么意思,我是新...
- sed -e "/grep/d" 是什么意思...
- 谁能够帮我解决LINUX 2.6 10...
给主人留下些什么吧!~~
评论热议
0 0
- select 和 epoll的编程实现区别
- select 和 epoll的编程实现区别(2)
- Select和epoll的区别
- Select和epoll的区别
- Select和epoll的区别
- select和epoll的区别
- Select和epoll的区别
- select和epoll的区别
- Select和epoll的区别
- Select和epoll的区别
- epoll 和 select 的区别
- select和Epoll的区别
- epoll和select的区别
- epoll和select的区别
- epoll和select的区别
- Select和epoll的区别
- select和epoll的区别
- select 和 epoll的区别
- Java socket示例(demo)TCP/IP
- Android 模拟器(JAVA)与C++ socket 通讯(IP设置)
- 基于 Android NDK 的学习之旅-----环境搭建[Eclipse ADT集成Cygwin编译]
- Android使用contentprovide实现对其他应用数据库的读写
- select 和 epoll的编程实现区别
- select 和 epoll的编程实现区别(2)
- linux非阻塞式socket编程之select()用法
- fd_set 用法 socket
- necessitas
- 进程间通信——管道
- 获取Java项目根目录 N多方法(转载)
- appledoc格式
- 世界首富如何炼成? 看盖茨20条箴言
- Java异常处理--将try/catch区段置于循环之外
原创粉丝点击
热门IT博客
热门问题
老师的惩罚
人脸识别
我在镇武司摸鱼那些年
重生之率土为王
我在大康的咸鱼生活
盘龙之生命进化
天生仙种
凡人之先天五行
春回大明朝
姑娘不必设防,我是瞎子
铝丝手工制作大全
铁丝工艺品制作图解
金立手机桌面主题
自制手机wifi天线铜丝
铜仁旅游
铜仁学院
铜仁市
铜仁梵净山
铜仁网
铜仁大峡谷
铜仁古城
贵阳铜仁
铜仁火车站
铜仁机场
铜仁景点
铜仁邮编
铜仁志愿者
铜仁高铁站
铜仁南站
铜仁在哪
铜仁碧江区
铜仁吧
铜仁门户网
铜仁特产
贵州铜仁市
铜仁一中
铜仁地区
铜仁天生桥
铜仁两日游
铜仁教育网
铜仁景区
铜仁在哪里
铜仁养猪场
铜仁站
长沙去铜仁
长沙 铜仁
铜仁医院
铜仁小吃
到铜仁
贵州省铜仁
铜仁特色