使用epoll的多个UDP套接字 – 无法接收数据

我试图使用epoll从多个UDP套接字接收数据。 这是一个测试程序,它没有确切数量的套接字。(为了测试目的,它设置为50.)下面的程序没有收到任何数据,它被卡在epoll_wait(),因为我已经给它-1等待直到得到数据。 但是没有得到任何。

#include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #define MAX_CON (50) typedef struct UDPMessage { unsigned short hdr; unsigned short CC1; unsigned short CC2; unsigned char data[1472]; unsigned short CC3; } UDPPacket; static struct epoll_event *events; int create_sockets(unsigned int port); int create_sockets(unsigned int port) { int sock, flag = 1; struct sockaddr_in sock_name; /* Create a datagram socket*/ sock = socket(PF_INET, SOCK_DGRAM, 0); /* Setting the socket to non blocking*/ fcntl(sock, F_SETFL, O_NONBLOCK); if (sock < 0) { perror("socket"); exit(EXIT_FAILURE); } /* Set the reuse flag. */ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)) < 0) { perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)"); exit(EXIT_FAILURE); } /* Give the socket a name. */ sock_name.sin_family = AF_INET; sock_name.sin_port = htons(port); sock_name.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(sock,(struct sockaddr *) &sock_name, sizeof(sock_name)) < 0) { perror("bind"); exit(EXIT_FAILURE); } return sock; } int main(int argc, char *argv[]) { fd_set master; fd_set read_fds; struct sockaddr_in serveraddr; struct sockaddr_in clientaddr; int fdmax=0; int newfd; int nbytes; int epfd = -1; int res = -1; struct epoll_event ev; int i=0; int index = 0; int client_fd = -1; int SnumOfConnection = 0; UDPPacket UDPPacket_obj; struct sockaddr_in client_sockaddr_in; struct sockaddr_in server_sockaddr_in; int sockfd[12]={0}; int PORTS[12] = { 10011,10012,10013,10021,10022,10023,10031,10032,10033,10041,10042,10043}; //TEST only 12 ports int port_index=0; int sockaddr_in_length=0; printf("In main\n"); /* Create sockets with the above list of ports */ for( port_index=0;port_index fdmax) fdmax = sockfd[port_index]; } printf("after soc creation\n"); sockaddr_in_length = sizeof(struct sockaddr_in); events = calloc(MAX_CON, sizeof(struct epoll_event)); if ((epfd = epoll_create(MAX_CON)) == -1) /* epoll_create */ { perror("epoll_create"); exit(1); } ev.events = EPOLLIN; ev.data.fd = fdmax; for( port_index=0;port_index<12;port_index++) { if (epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd[port_index], &ev) < 0) /* epoll_ctl */ { perror("epoll_ctl"); exit(1); } } while(1) { printf("Before epoll_wait\n"); res = epoll_wait(epfd, events, MAX_CON, -1); /* epoll_wait */ printf("After epoll_wait\n"); client_fd = events[index].data.fd; for (index = 0; index < MAX_CON; index++) { printf("start\n"); if (events[index].events & EPOLLHUP) { if (epoll_ctl(epfd, EPOLL_CTL_DEL, client_fd, &ev) < 0) { perror("epoll_ctl"); } close(client_fd); break; } printf("before EPOLLIN check\n"); if (events[index].events & EPOLLIN) { if((nbytes = recvfrom(client_fd,&UDPPacket_obj,sizeof(UDPPacket),0, (struct sockaddr *)&client_sockaddr_in, &sockaddr_in_length)) <=0) { if(nbytes == 0) { printf("socket %d hung up\n", client_fd); } else { printf("recv() error lol! %d", client_fd); perror(""); } if (epoll_ctl(epfd, EPOLL_CTL_DEL, client_fd, &ev) < 0) { perror("epoll_ctl"); } //close(client_fd); } printf("Data recv=%s\n",UDPPacket_obj.data); } } } //end of while return 0; } 

您只等待单个套接字上的事件,即fdmax中的fdmax

您需要添加要轮询的所有套接字。

这是一个非常古老的线程。

但进入while(1)循环,行:

 client_fd = events[index].data.fd; 

是完全相同的:

 client_fd = fdmax ; 

更清楚:

(A)你想要推荐一个fd。 这是您在命令中传递的那个

 epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd[port_index], &ev) 

被轮询的fd是sockfd [port_index]

(B)并且在返回的事件结构中存在要测试的fd。 在您的代码中,您可以在以下行中访问它:

 client_fd = events[index].data.fd; 

此fd可能与轮询不同。 返回的fd是在您通过以下方式传递给epoll_ctl的事件结构中:

 ev.data.fd = fdmax; : epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd[port_index], &ev) 

返回的fd是de ev内部。 即使您在另一个套接字中收到一个事件,您获得的事件结构在event.data.fd中也有fd_max。

所以,当你执行:

 client_fd = events[index].data.fd; 

你总是得到fd_max。