epoll

    xiaoxiao2022-07-02  118

    由epoll返回的事件可以有EPOLLIN,EPOLLOUT,EPOLLRDHUP,EPOLLPRI,EPOLLERR,EPOLLHUP。

     

    关于EPOLLIN,EPOLLOUT,EPOLLPRI相信大家都熟悉,EPOLLIN代表有数据可读,EPOLLOUT代表可写,EPOLLPRI代表有带外数据可读。

     

    接下来让我们关注一下EPOLLRDHUP,EPOLLERR,EPOLLHUP事件什么时候会发生呢:

    EPOLLRDHUP:对端正常关闭的时候会触发该事件以及EPOLL_IN事件

    EPOLLHUP:对端发来RST会触发该事件和EPOLL_ERR事件以及EPOLLRDHUP,EPOLLIN, EPOLLOUT

    EPOLLERR:目前测试的收到RST会触发该事件(超时事件不知道会不会触发,没测试,麻烦有测试过的交流下,谢谢了)

     

    下面是测试代码:

    服务器端:如果想要测试自己想测试的时间,改一下ev.events就可以了 #include<sys/types.h> #include<sys/socket.h> #include<stdio.h> #include<string.h> #include<arpa/inet.h> #include<errno.h> #include<unistd.h> #include <sys/epoll.h> #include<fcntl.h> #include<sys/epoll.h> #include<assert.h> int createSocket(sa_family_t family){ int fd = socket(family,SOCK_STREAM | SOCK_CLOEXEC, 0); assert(fd > 0); return fd; } void bindAddr(const int &fd,const struct sockaddr *addr){ if(addr->sa_family == AF_INET){ int ret = bind(fd,addr,sizeof(struct sockaddr_in)); assert(ret != -1); } else if(addr->sa_family == AF_INET6){ int ret = bind(fd,addr,sizeof(struct sockaddr_in6)); assert(ret != -1); } } void setReuseAddr(const int &fd){ int optval = 1; int ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,&optval, static_cast<socklen_t>(sizeof optval)); assert(ret != -1); } int main(){ struct sockaddr_in addr; memset(&addr,0,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(60000); int acceptFd = createSocket(addr.sin_family); setReuseAddr(acceptFd); bindAddr(acceptFd,(struct sockaddr *)&addr); int ret = listen(acceptFd, SOMAXCONN); if(ret < 0){ assert(-1); } struct sockaddr_in6 peerAddr; socklen_t len = sizeof(peerAddr); int fd = accept(acceptFd,(struct sockaddr*)(&peerAddr),&len); if(fd < 0){ printf("accept err\n"); } printf("accept\n"); int epollFd; if((epollFd = epoll_create(1)) < 0) printf("create err\n"); struct epoll_event ev; memset(&ev,0,sizeof(ev)); ev.events = EPOLLIN | EPOLLRDHUP; ev.data.fd = fd; if(epoll_ctl(epollFd,EPOLL_CTL_ADD,fd,&ev) < 0) printf("ctl err\n"); struct epoll_event happen; while(1){ int num = epoll_wait(epollFd,&happen,1,-1); if(num == 1){ printf("happen\n"); if(happen.events & EPOLLIN && happen.events & EPOLLRDHUP){ printf("epollrdhup\n"); } if(happen.events & EPOLLERR) printf("epollup\n"); } } return 0; } 客户端:设置SO_LINGER是为了让客户端发出RST #include<sys/types.h> #include<sys/socket.h> #include<stdio.h> #include<string.h> #include<arpa/inet.h> #include<errno.h> #include<unistd.h> #include <sys/epoll.h> #include<fcntl.h> #include<assert.h> int main(){ int fd = socket(AF_INET,SOCK_STREAM,0); if(fd < 0) printf("socket err\n"); struct sockaddr_in addr; memset(&addr,0,sizeof(addr)); addr.sin_family = AF_INET; char b[] = "192.168.140.133"; unsigned char buf[sizeof(struct in6_addr)]; if(inet_pton(AF_INET,b,(void *)(&addr.sin_addr.s_addr))<0){ printf("err 1\n"); } addr.sin_port = htons(60000); if(connect(fd,(struct sockaddr*)(&addr),sizeof(sockaddr_in)) < 0 ){ printf("err 2\n"); printf("%s\n",strerror(errno)); } printf("connect\n"); sleep(5); //close(fd); struct linger a; a.l_onoff = 1; a.l_linger = 0; int ret = setsockopt(fd, SOL_SOCKET, SO_LINGER ,&a, static_cast<socklen_t>(sizeof a)); assert(ret != -1); return 0; }

     

    .

    最新回复(0)