2013-03-28 193 views
2

我想接收来自不同客户端的数据(客户端的数量是固定的,比如说10),并且每个客户端在5个不同的预定义端口上发送数据, 1个端口5000,5001,5002等)。所有客户端可以同时发送数据。 (以上所有都是固定的)多线程接收来自多个UDP客户端的数据

在TCP中说,我可以创建多个线程,为我们接受的每个连接,如下所示。 UDP是无连接的,那么我们如何才能为每个UDP客户端(UDP端口)创建一个线程来处理并发数据呢?就像每个具有receivefrom()函数的线程来获取数据一样。

// UDP服务器

#define BUFLEN 512 

#define CLIENT1_PORT1 5000 
#define CLIENT1_PORT2 5001 
#define CLIENT1_PORT3 5002 

#define CLIENT2_PORT1 5050 
#define CLIENT2_PORT2 5051 
#define CLIENT2_PORT3 5052 

#define CLIENT3_PORT1 6000 
#define CLIENT3_PORT2 6001 
#define CLIENT3_PORT3 6002 

void diep(char *s) { 
    perror(s); 
    exit(1); 
} 

int main(void) { 
    struct sockaddr_in client1_sockaddr_1, client1_sockaddr_2,client2_sockaddr_1,client2_sockaddr_2, si_other; 
    int c1_sockfd_1,c1_sockfd_2, c2_sockfd_1,c2_sockfd_2, i, slen = sizeof(si_other); 

    char buf[BUFLEN]; 

    /******for client 1 port1 **********/ 
    if((c1_sockfd_1 = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 
    diep("socket"); 

    memset((char *) &client1_sockaddr_1, 0, sizeof(client1_sockaddr_1)); 

    client1_sockaddr_1.sin_family = AF_INET; 
    client1_sockaddr_1.sin_port = htons(CLIENT1_PORT1); 
    client1_sockaddr_1.sin_addr.s_addr = htonl(INADDR_ANY); 

    if(bind(c1_sockfd_1, (struct sockaddr *) &client1_sockaddr_1, sizeof(client1_sockaddr_1)) == -1) 
    diep("bind"); 

    if((c2_sockfd_1 = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 
    diep("socket"); 

    /*******for client 2 port1 *******/ 
    memset((char *) &client2_sockaddr_1, 0, sizeof(client2_sockaddr_1)); 

    client2_sockaddr_1.sin_family = AF_INET; 
    client2_sockaddr_1.sin_port = htons(CLIENT2_PORT1); 
    client2_sockaddr_1.sin_addr.s_addr = htonl(INADDR_ANY); 

    if(bind(c1_sockfd_2, (struct sockaddr *) &client2_sockaddr_1, sizeof(client2_sockaddr_1)) == -1) 
    diep("bind"); 

//Receive from clients 
while(1) { 

    /*How to create threads at this point and have a separate recvfrom for each client port ??*/ 
    if(recvfrom(c1_sockfd_1, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == -1) 
     diep("recvfrom()"); 

    printf("Recieved packet from %s: %d\nData: %s\n\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port), buf); 
    } 
    close(c1_sockfd_1); 
    return 0; 
} 

更新 我有一个像每个客户5口,共5×10个插槽和数据将在几毫秒内收到simultaneously.Here数据包的时间间隔发送每个端口都有不同的大小。数据包与Header和CRC一起发送。为了跟踪和重新请求丢失的数据包,是否有分组号码是一个好主意?

(或)使用UDP跟踪丢失的数据包和请求有哪些不同的方法?

回答

1

你不需要多个线程。

如果你的瓶颈是IO,线程不会帮助。

如果您的瓶颈是处理/ CPU,请在一个线程中接受它们,然后分派到多个线程。

+0

谢谢。我还没有确定瓶颈。我在想,既然数据流将持续,数据每隔几毫秒就会发送一次,我认为我可以使用线程更好地处理数据。接受什么机制,我派遣到几个线程? – m4n07

+0

我会建议一种同步消息队列(例如带锁的std :: deque)。线程经常会发生违反直觉的事情,并且实际上它可能会减慢速度。线程在CPU密集型代码(如重型数学计算)时非常有用。 –

+0

他确实需要多个线程以及时和公平的方式从多个端口读取,除非他使用非阻塞的I/O,他没有提到。他没有说任何有关瓶颈的事情。 UDP中没有接受步骤。 -1 – EJP

3

线程的替代方法是select()函数,它提供了同步I/O复用。你可以将你的5 socket fds提供给select()函数,并等待其中的一个准备好数据。冲洗并重复。

请查看手册页:http://linux.die.net/man/2/select或网上的许多教程。

+0

谢谢。其实际上每个客户端5个端口。 (10个客户端* 5 = 50个套接字)。 5端口中的每一个都获得不同的数据。获取数据后,会有一些IO写入涉及的文件。 – m4n07

1

如果你想要一个线程每个端口的解决方案:对于每个端口号p创建一个线程并将它作为参数传递,然后线程将执行:socket(); bind(p),while(1){recvfrom();发给(); }

+0

谢谢巴哈。看到其他评论和线程同步等我想到更好的方法来做到这一点。 – m4n07

相关问题