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

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

问题描述:

我试着去接受使用epoll的多个UDP套接字的数据。这是一个测试程序,它没有插座的确切数字。(用于测试目的,其设定为50)下面的程序没有收到任何数据,并将其卡在epoll_wait(),因为我已经给它-1不断地等待直到它获得数据。但没有得到任何。多个UDP套接字使用epoll的 - 无法接收数据

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <sys/epoll.h> 
#include <fcntl.h> 

#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<12;port_index++) 
     { 
       sockfd[port_index]=create_sockets(PORTS[port_index]); 
       if(sockfd[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

您需要添加要轮询所有插座。

+0

@ m4n07您需要在创建epoll描述符之后执行此操作,当然也需要使用正确初始化的epoll_event结构。不知道你是否需要每个插座。 – 2013-04-26 07:39:15

+0

谢谢,我已经更新了code.Now循环的推移而没有接收到的数据。 – m4n07 2013-04-26 08:58:19

+0

@ m4n07在调用'epoll_ctl'之前,您仍然忘记了设置'ev.data.fd'。你也许需要使用那个独特的结构(我不确定),所以也是那个数组。 – 2013-04-26 09:05:04

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

但进入而(1)循环,该行:

client_fd = events[index].data.fd; 

是完全一样的:

client_fd = fdmax ; 

作为更加清晰:

(A)有一个你想轮询你。这是你在命令

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。

+0

谢谢。如果时间允许,我会去看看。 – m4n07 2017-10-25 09:26:40