socket programming program how geeksforgeeks example c sockets network-programming udp epoll

programming - MĂșltiples sockets UDP que usan epoll: no pueden recibir datos



socket udp java (2)

Solo está esperando eventos en un solo socket, el de fdmax .

Necesita agregar todos los sockets que desea sondear.

Estoy tratando de recibir datos de múltiples sockets UDP usando epoll. Este es un programa de prueba que no tiene el número exacto de sockets. (Para propósitos de prueba está configurado como 50). El programa de abajo no recibe ningún dato y se bloquea en epoll_wait (), ya que le he dado -1 espera indefinidamente hasta que obtiene datos. Pero no obtiene ninguno.

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


Este es un hilo muy viejo.

Pero en el ciclo while (1), la línea:

client_fd = events[index].data.fd;

es exactamente lo mismo de:

client_fd = fdmax ;

Siendo más claro:

(A) Hay un fd que quiere sondear. Este es el que pasaste en el comando

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

El fd que se sondea es el sockfd [port_index]

(B) Y está el fd que quiere probar en caso de que se devuelva struct. En su código, accede a él en la línea:

client_fd = events[index].data.fd;

Este fd puede no ser el mismo sondeo. La fd devuelta está en la estructura de evento que pasaste a epoll_ctl por:

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

El fd devuelto está dentro de ev. Incluso si recibe un evento en otro socket, la estructura de eventos que obtiene tiene fd_max en event.data.fd.

Entonces, cuando ejecutas:

client_fd = events[index].data.fd;

Siempre obtienes fd_max.