简体   繁体   English

多线程从多个UDP客户端接收数据

[英]Multithreading to receive data from multiple UDP clients

I wanted to receive data from different clients(Number of clients is fixed,say 10) ,And each of the clients send data on 5 different predefined ports which wont change.(example, client 1 ports 5000,5001,5002,etc).All the clients can send data simultaneously. 我想从不同的客户端接收数据(客户端的数量是固定的,例如10),并且每个客户端都在5个不会更改的预定义端口上发送数据(例如,客户端1端口5000、5001,5002等)。所有客户端可以同时发送数据。 (All the above are fixed) (以上所有内容都是固定的)

Say in TCP, i can create multiple threads,one for each of the connection we accept ,like the below. 说在TCP中,我可以创建多个线程,为我们接受的每个连接创建一个线程,如下所示。 UDP is connectionless,So how can we create one thread per UDP client(UDP port) to handle the concurrent data?Like each thread having a receivefrom() function to get data. UDP是无连接的,那么如何为每个UDP客户端(UDP端口)创建一个线程来处理并发数据呢?

//UDP Server // 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;
}

Update I have like 5 ports per client, totally 5 * 10 sockets and data will be sent in time gaps of few milliseconds simultaneously.Here packets received on each port are of different sizes. 更新我每个客户端有5个端口,总共5个10个套接字,数据将在几毫秒的时间间隔内同时发送。每个端口接收到的数据包大小不同。 The packets are sent with Header and CRC. 数据包与标头和CRC一起发送。 Is it a good idea to have packet numbers in order to track and rerequest the lost packets ? 拥有数据包编号以便跟踪和重新请求丢失的数据包是一个好主意吗?

(or) What are the different ways to track the lost packets and request for them using UDP? (或)使用UDP跟踪丢失的数据包和请求数据包有哪些不同的方法?

An alternative to threads is select() function, which provides synchronous I/O multiplexing. 线程的替代方法是select()函数,该函数提供同步I / O复用。 You can provide your 5 socket fds to the select() function and wait until one of them is ready with data. 您可以将5个套接字fds提供给select()函数,并等待其中之一准备好数据。 Rinse and repeat. 冲洗并重复。

Look at the man page: http://linux.die.net/man/2/select or many tutorials on the web. 查看手册页: http : //linux.die.net/man/2/select或网络上的许多教程。

You do not need multiple threads. 您不需要多个线程。

If your bottleneck is IO, threads are not going to help. 如果您的瓶颈是IO,线程将无济于事。

If your bottleneck is processing/CPU, accept them all in one thread and then dispatch to several threads. 如果您的瓶颈在处理/ CPU,请在一个线程中接受它们,然后分派到多个线程。

if you want a thread per port solution: for each port number p create a thread and pass it p as parameter then the thread will do: socket(); 如果您希望每个端口有一个线程解决方案:对于每个端口号p创建一个线程并将其作为参数传递给p,则该线程将执行以下操作:socket(); bind(p), while (1) { recvfrom(); bind(p),而(1){recvfrom(); sendto(); 发给(); } }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM