epoll的一点思考(5)
来源:互联网 发布:射频电路仿真软件 编辑:程序博客网 时间:2024/05/16 10:07
epoll 同时触发in与out
通过测试发现out与in事件可以同时触发的,测试代码如下:
#include <iostream>#include <sys/socket.h>#include <sys/epoll.h>#include <netinet/in.h>#include <arpa/inet.h>#include <fcntl.h>#include <unistd.h>#include <stdio.h>#include <errno.h>#include <netinet/tcp.h>using namespace std;#define MAXLINE 5#define OPEN_MAX 100#define LISTENQ 20#define SERV_PORT 6002#define INFTIM 1000int socket_set_keepalive( int fd){ int ret, error, flag, alive, idle, cnt, intv; /* Set: use keepalive on fd */ alive = 1; if (setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, &alive, sizeof alive) != 0) { printf ("Set keepalive error: %s.\n" , strerror (errno)); return -1; } /* 10秒钟无数据,触发保活机制,发送保活包 */ idle = 10; if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE , &idle, sizeof idle) != 0) { printf ("Set keepalive idle error: %s.\n" , strerror (errno)); return -1; } /* 如果没有收到回应,则5秒钟后重发保活包 */ intv = 5; if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL , &intv, sizeof intv) != 0) { printf ("Set keepalive intv error: %s.\n", strerror (errno)); return -1; } /* 连续3次没收到保活包,视为连接失效 */ cnt = 3; if (setsockopt(fd, SOL_TCP, TCP_KEEPCNT , &cnt, sizeof cnt) != 0) { printf ("Set keepalive cnt error: %s.\n", strerror (errno)); return -1; } return 0;}void setnonblocking(int sock){ int opts; opts=fcntl(sock,F_GETFL); if(opts<0) { perror("fcntl(sock,GETFL)"); exit(1); } opts = opts|O_NONBLOCK; if(fcntl(sock,F_SETFL,opts)<0) { perror("fcntl(sock,SETFL,opts)"); exit(1); } }int main(){ int i, maxi, listenfd, connfd, sockfd,epfd,nfds; ssize_t n; char line[MAXLINE]; socklen_t clilen; //声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件 struct epoll_event ev,events[20]; //生成用于处理accept的epoll专用的文件描述符 epfd=epoll_create(256); struct sockaddr_in clientaddr; struct sockaddr_in serveraddr; listenfd = socket(AF_INET, SOCK_STREAM, 0); int reuse = 1;setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); //把socket设置为非阻塞方式 //setnonblocking(listenfd); //设置与要处理的事件相关的文件描述符 ev.data.fd=listenfd; //设置要处理的事件类型 ev.events=EPOLLIN|EPOLLET; //ev.events=EPOLLIN; //注册epoll事件 epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev); bzero(&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; char *local_addr="0.0.0.0"; inet_aton(local_addr,&(serveraddr.sin_addr));//htons(SERV_PORT); serveraddr.sin_port=htons(SERV_PORT); bind(listenfd,(sockaddr *)&serveraddr, sizeof(serveraddr)); listen(listenfd, LISTENQ); cout << listenfd << endl; maxi = 0; for ( ; ; ) { //等待epoll事件的发生 nfds=epoll_wait(epfd,events,20,-1); cout << "EPOLL wait end" << endl; //处理所发生的所有事件 for(i=0;i<nfds;++i) { cout << "nfds:" << nfds << endl; if(events[i].data.fd==listenfd) { clilen = sizeof(clientaddr); connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen); if(connfd<0){ perror("connfd<0"); exit(1); } setnonblocking(connfd); //socket_set_keepalive(connfd); char *str = inet_ntoa(clientaddr.sin_addr); cout << "accapt a connection from " << str << endl; //设置用于读操作的文件描述符 ev.data.fd=connfd; //设置用于注测的读操作事件 ev.events=EPOLLOUT|EPOLLET|EPOLLIN; //ev.events=EPOLLIN; //注册ev epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev); /* char buf[1024] = "abc1234567890abc1234567890abc1234567890abc1234567890abc1234567890abc1234567890abc1234567890abc1234567890"; int i = 0; while(1) { if (send(connfd, buf, strlen(buf) + 1, 0) < 0) { cout << "error-->" << strerror(errno) << endl; break; } usleep(100000); cout << ++i << endl; } */ //设置用于注测的读操作事件 //ev.events=EPOLLIN|EPOLLET; //ev.events=EPOLLIN; //注册ev // epoll_ctl(epfd,EPOLL_CTL_MOD,connfd,&ev); sleep(10); } else { if(events[i].events&EPOLLIN) { cout << "EPOLLIN" << endl; /* sockfd = events[i].data.fd; char buf; int n = 0; if ( (n = read(sockfd, &buf, 1)) > 0) { printf("%c\n",buf); } printf("%d\n",n); if (n == 0) { ev.data.fd=sockfd; epoll_ctl(epfd,EPOLL_CTL_DEL,sockfd,&ev); } else { cout << "error-222--->" << strerror(errno) << endl; ev.data.fd=sockfd; ev.events=EPOLLOUT|EPOLLET|EPOLLIN; epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); } */ } if(events[i].events&EPOLLOUT) { cout << "EPOLLOUT" << endl; //cout << "EPOLLOUT END" << endl; /* sockfd = events[i].data.fd; //write(sockfd, line, n); //设置用于读操作的文件描述符 // sleep(5); ev.data.fd=sockfd; //设置用于注测的读操作事件 ev.events=EPOLLOUT|EPOLLET|EPOLLIN; //修改sockfd上要处理的事件为EPOLIN epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); */ } } } } return 0;}
在accept之后监听in与out事件,然后sleep(10),客户端在这10秒内发送数据,等待epoll_wait返回后,分别进入in与out分值,注意if (in) 然后if (out),而不是else if (out)。
- epoll的一点思考(5)
- epoll的一点思考(2)
- epoll的一点思考(1)
- epoll一点思考(3)
- epoll一点思考(4)
- epoll的一些思考
- epoll的一些思考
- DES加密的一点思考(一)
- DES加密的一点思考(二)
- 关于HIT的一点思考(1)
- 多线程的一点思考
- 最近的一点思考
- 暑假的一点思考
- TreeView的一点思考
- JNDI 的一点思考
- 开发的一点思考
- 分层的一点思考
- getchar()的一点思考
- js监听浏览器,关闭,刷新(兼容IE6+,Firefox,Chrome,Safari)
- 基于QWidget类的动态库在4.8.1隐式调用时出现staticMetaObject' of dllimport'd class的解决办法
- 获取资源string /string【】
- 生活不只是生存:教你学会生活
- 利用POI组件 导入导出excel
- epoll的一点思考(5)
- Google Nexus (i9250)fastboot 升级4.2
- Javascript工具包
- IOS setNeedsDisplay 和 setNeedsLayout
- ABAP通过交互界面向自建表里添加/删除数据
- oracle提高查询效率
- Struts2.0表单标签
- MyEclipse8.5破解方法
- hive Timestamp类型慎用