无法接收数据 - 使用epoll的多个UDP套接字 [英] Multiple UDP sockets using epoll - Not able to receive data

查看:288
本文介绍了无法接收数据 - 使用epoll的多个UDP套接字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&string.h中GT;
#包括LT&;&unistd.h中GT;
#包括LT&; SYS / types.h中>
#包括LT&; SYS / socket.h中>
#包括LT&; netinet / in.h中>
#包括LT&; ARPA / inet.h>
#包括LT&; SYS / epoll.h>
#包括LT&;&fcntl.h GT;的#define MAX_CON(50)
typedef结构UDPMessage
{
  无符号短HDR;
  无符号短CC1;
  无符号短CC2;
  unsigned char型数据[1472];
  无符号短CC3;
} UDPPacket;静态结构epoll_event *事件;
诠释create_sockets(unsigned int类型端口);诠释create_sockets(unsigned int类型端口)
{
        INT袜子,标志= 1;
        结构SOCKADDR_IN sock_name;        / *创建一个数据报套接字* /
        袜子=插座(PF_INET,SOCK_DGRAM,0);
        / *套接字设置为非阻塞* /
        的fcntl(袜子,F_SETFL,O_NONBLOCK);        如果(袜子℃,)
        {
                PERROR(插座);
                出口(EXIT_FAILURE);
        }
        / *设置重用标志。 * /
        如果(setsockopt的(袜子,SOL_SOCKET,SO_REUSEADDR,&安培;标志的sizeof(标志))小于0)
        {
                PERROR(setsockopt的(SOL_SOCKET,SO_REUSEADDR));
                出口(EXIT_FAILURE);
        }
        / *给套接字的名称。 * /
        sock_name.sin_family = AF_INET;
        sock_name.sin_port = htons(端口);
        sock_name.sin_addr.s_addr = htonl(INADDR_ANY);
        如果(绑定(袜子,(结构sockaddr *)及sock_name,sizeof的(sock_name))小于0)
        {
                PERROR(绑定);
                出口(EXIT_FAILURE);
        }
        返回袜子;
}INT主(INT ARGC,CHAR *的argv [])
{
        FD_SET掌握;
        FD_SET read_fds;
        结构SOCKADDR_IN serveraddr;
        结构SOCKADDR_IN clientaddr;
        INT fdmax = 0;
        INT newfd;
        INT为nbytes;
        INT的epfd = -1;
        中期业绩= -1;
        结构epoll_event EV;
        INT I = 0;
        INT索引= 0;
        INT client_fd = -1;        INT SnumOfConnection = 0;        UDPPacket UDPPacket_obj;
        结构SOCKADDR_IN client_sockaddr_in;
        结构SOCKADDR_IN server_sockaddr_in;        INT的sockfd [12] = {0};
        INT宝姿[12] = {} 10011,10012,10013,10021,10022,10023,10031,10032,10033,10041,10042,10043; //测试只有12个端口
        INT port_index = 0;
        INT sockaddr_in_length = 0;        的printf(在主\\ n);        / *与端口上面所列内容创建插座* /
        为(port_index = 0; port_index&下; 12; port_index ++)
        {
                的sockfd [port_index] = create_sockets(宝姿[port_index]);
                如果(的sockfd [port_index> fdmax)
                        fdmax =的sockfd [port_index]
        }
        的printf(SOC创建\\ n后);        sockaddr_in_length = sizeof的(结构SOCKADDR_IN);        事件=释放calloc(MAX_CON,sizeof的(结构epoll_event));
        如果((的epfd = epoll_create(MAX_CON))== -1)/ * * epoll_create /
        {
                PERROR(epoll_create);
                出口(1);
        }
        ev.events = EPOLLIN;
        ev.data.fd = fdmax;        为(port_index = 0; port_index&下; 12; port_index ++)
        {
            如果(epoll_ctl(epfd的,EPOLL_CTL_ADD,的sockfd [port_index],&放大器; EV)小于0)/ * epoll_ctl * /
            {
                  PERROR(epoll_ctl);
                  出口(1);
            }
         }         而(1)
        {
                的printf(epoll_wait之前\\ n);
                RES = epoll_wait(epfd的,事件,MAX_CON,-1); / * epoll_wait * /
                的printf(epoll_wait \\ n后);
                client_fd =事件[指数] .data.fd;                对于(指数= 0;指数 - LT; MAX_CON;指数++)
                {
                        的printf(开始\\ n);
                        如果(事件[指数] .events&安培; EPOLLHUP)
                        {
                                如果(epoll_ctl(epfd的,EPOLL_CTL_DEL,client_fd,&放大器; EV)℃,){
                                        PERROR(epoll_ctl);
                                }
                                关闭(client_fd);
                                打破;
                        }
                        的printf(EPOLLIN检查之前\\ n);
                        如果(事件[指数] .events&安培; EPOLLIN){
                                如果((为nbytes = recvfrom的(client_fd,&安培; UDPPacket_obj,sizeof的(UDPPacket),0,
                                                                (结构sockaddr *)及client_sockaddr_in,
                                                                &放大器; sockaddr_in_length))≤; = 0)                                {
                                        如果(为nbytes == 0){
                                                的printf(插座%d个挂了\\ n,client_fd);
                                        }
                                        其他{
                                                输出(的recv()错误笑%d个!,client_fd);
                                                PERROR();
                                        }                                        如果(epoll_ctl(epfd的,EPOLL_CTL_DEL,client_fd,&放大器; EV)℃,){
                                                PERROR(epoll_ctl);
                                        }
                                        //关闭(client_fd);
                                }
                                的printf(数据的recv =%s的\\ n,UDPPacket_obj.data);
                        }
                }
        } //而结束
        返回0;
}


解决方案

您只等着在一个单一的套接字事件,一个在 fdmax

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

Im trying to receive data from multiple UDP sockets using epoll. This is a test program it doesn't have exact number of sockets.( For testing purpose its set as 50.) The below program doesn't receive any data and it gets stuck at epoll_wait(), since i have given -1 it waits indefinetly till it gets data. But doesn't get any.

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

解决方案

You are only waiting for events on one single socket, the one in fdmax.

You need to add all sockets you want to poll.

这篇关于无法接收数据 - 使用epoll的多个UDP套接字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆