2013-04-26 4 views
0

epoll을 사용하여 여러 개의 UDP 소켓에서 데이터를 수신하려고합니다. 이것은 정확한 소켓 수를 가지고 있지 않은 테스트 프로그램입니다. (테스트 목적을 위해 50으로 설정되었습니다.) 아래 프로그램은 어떤 데이터도받지 못합니다. epoll_wait()에서 멈추게됩니다. 데이터가 도착할 때까지 기다립니다. 그러나 아무것도 얻지 않는다.epoll을 사용하는 다중 UDP 소켓 - 데이터를 수신 할 수 없습니다.

#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; 
} 

답변

2

하나의 단일 소켓에서 이벤트를 기다리는 중입니다. 하나는 fdmax입니다.

모두 폴링하려는 소켓을 추가해야합니다.

+0

@ m4n07 당신은 epoll 디스크립터를 만들었고, 물론 제대로 초기화 된'epoll_event' 구조체를 사용해야합니다. 소켓 당 하나씩 필요하면 확실하지 않습니다. –

+0

감사합니다. 코드를 업데이트했습니다. 이제 데이터가 수신되지 않고 루프가 진행됩니다. – m4n07

+0

@ m4n07'epoll_ctl'을 호출하기 전에'ev.data.fd'를 설정하는 것을 잊었습니다. 당신은 _might_ 너무 독특한 구조를 사용해야합니다 (나는 그것에 대해 잘 모르겠습니다). 그래서 배열도 마찬가지입니다. –

0

이것은 매우 오래된 스레드입니다.

그러나 잠시 (1) 루프 라인에

:

client_fd = fdmax ; 

이 더 명확 인 :

이 이

(A)가있다

client_fd = events[index].data.fd; 

정확히의 동일 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는 ev 내부에 있습니다. 다른 소켓에서 이벤트를 받았다고해도 event.data.fd에는 fd_max가 있습니다. 그래서

, 당신은 실행할 때 :

client_fd = events[index].data.fd; 

당신은 항상 fd_max 얻을.

+0

감사합니다. 시간이 허락하면 나는 한 번 살펴볼 것입니다. – m4n07

관련 문제