多个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
。
您需要添加要轮询所有插座。
答
这是一个非常古老的线程。
但进入而(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
@ m4n07您需要在创建epoll描述符之后执行此操作,当然也需要使用正确初始化的epoll_event结构。不知道你是否需要每个插座。 – 2013-04-26 07:39:15
谢谢,我已经更新了code.Now循环的推移而没有接收到的数据。 – m4n07 2013-04-26 08:58:19
@ m4n07在调用'epoll_ctl'之前,您仍然忘记了设置'ev.data.fd'。你也许需要使用那个独特的结构(我不确定),所以也是那个数组。 – 2013-04-26 09:05:04