【发布时间】:2021-10-09 19:18:36
【问题描述】:
我有两个 UDP 连接,我正在尝试添加它们以使用 epoll()。我正在看这个例子:
https://programmer.ink/think/epoll-for-linux-programming.html
我已经粘贴了下面的代码。
一开始他们创建了一个 epoll 事件和一个 epoll 事件数组:
struct epoll_event ev,events[20];
我不确定为什么两者都需要。
然后他们打电话给epoll_wait():
nfds=epoll_wait(epfd,events,20,500);
并检索套接字:
if(events[i].data.fd==listenfd)
但是,events 没有填充在这三行之间。
-
那么
events[i].data.fd是如何包含socket文件描述符的呢? -
如果我们有一个包含文件描述符数据成员的
epoll_event数组,为什么要设置ev.data.fd=listenfd;?struct epoll_event ev,events[20]; //Generate epoll-specific file descriptors for processing accept s epfd=epoll_create(256); struct sockaddr_in clientaddr; struct sockaddr_in serveraddr; listenfd = socket(AF_INET, SOCK_STREAM, 0); //Set socket to non-blocking //setnonblocking(listenfd); //Set the file descriptor associated with the event to be processed ev.data.fd=listenfd; //Set the type of event to process ev.events=EPOLLIN|EPOLLET; //ev.events=EPOLLIN; //Register epoll events epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev); bzero(&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; char *local_addr="127.0.0.1"; inet_aton(local_addr,&(serveraddr.sin_addr));//htons(portnumber); serveraddr.sin_port=htons(portnumber); bind(listenfd,(struct sockaddr *)&serveraddr, sizeof(serveraddr)); listen(listenfd, LISTENQ); maxi = 0; for ( ; ; ) { //Waiting for the epoll event to occur nfds=epoll_wait(epfd,events,20,500); //Handle all events that occur for(i=0;i<nfds;++i) { if(events[i].data.fd==listenfd)//If a new SOCKET user is detected to be connected to a bound SOCKET port, establish a new connection. { connfd = accept(listenfd,(struct sockaddr *)&clientaddr, &clilen); if(connfd<0){ perror("connfd<0"); exit(1); } //setnonblocking(connfd); char *str = inet_ntoa(clientaddr.sin_addr); printf("accapt a connection from\n "); //Setting file descriptors for read operations ev.data.fd=connfd; //Set Read Action Events for Annotation ev.events=EPOLLIN|EPOLLET; //ev.events=EPOLLIN; //Register ev epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev); } else if(events[i].events&EPOLLIN)//If the user is already connected and receives data, read in. { printf("EPOLLIN\n"); if ( (sockfd = events[i].data.fd) < 0) continue; if ( (n = read(sockfd, line, MAXLINE)) < 0) { if (errno == ECONNRESET) { close(sockfd); events[i].data.fd = -1; } else printf("readline error\n"); } else if (n == 0) { close(sockfd); events[i].data.fd = -1; } if(n<MAXLINE-2) line[n] = '\0'; //Setting file descriptors for write operations ev.data.fd=sockfd; //Set Write Action Events for Annotation ev.events=EPOLLOUT|EPOLLET; //Modify the event to be handled on sockfd to EPOLLOUT //epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); } else if(events[i].events&EPOLLOUT) // If there is data to send { sockfd = events[i].data.fd; write(sockfd, line, n); //Setting file descriptors for read operations ev.data.fd=sockfd; //Set Read Action Events for Annotation ev.events=EPOLLIN|EPOLLET; //Modify the event to be processed on sockfd to EPOLIN epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); } } } return 0;}
【问题讨论】:
-
对
epoll_ctl()的调用将要轮询的FD添加到轮询FD。 -
@Barmar 但这里没有通过
events? -
events被传递给epoll_wait()。它会填充它。 -
ev用于添加事件等待epoll_ctl(),events是发生的事件列表。 -
知道了。如果你回答我会接受。
标签: c++ linux network-programming epoll