【问题标题】:Multithreading to receive data from multiple UDP clients多线程从多个 UDP 客户端接收数据
【发布时间】:2013-03-19 06:13:26
【问题描述】:

我想从不同的客户端接收数据(客户端的数量是固定的,比如 10 个),并且每个客户端都在 5 个不同的预定义端口上发送数据,这些端口不会改变。(例如,客户端 1 端口 5000、5001、5002,等)。所有客户端可以同时发送数据。 (以上都是固定的)

说在 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 个套接字,数据将在几毫秒的时间间隔内同时发送。每个端口上接收的数据包大小不同。数据包与 Header 和 CRC 一起发送。使用数据包编号来跟踪和重新请求丢失的数据包是个好主意吗?

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

【问题讨论】:

    标签: c linux sockets network-programming udp


    【解决方案1】:

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

    【讨论】:

    • 谢谢咩。看到其他 cmets 和线程同步等。我正在考虑更好的方法。
    【解决方案2】:

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

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

    【讨论】:

    • 谢谢。它实际上是每个客户端 5 个端口。 (10 个客户端 * 5 = 50 个套接字)。 5 个端口中的每一个都在获取不同的数据。获取数据后,有一些 IO 写入所涉及的文件。
    【解决方案3】:

    您不需要多个线程。

    如果您的瓶颈是 IO,线程将无济于事。

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

    【讨论】:

    • 谢谢。我还没有确定瓶颈。我在想,由于数据流将是连续的,并且每隔几毫秒发送一次数据,我认为我可以使用线程更好地处理。在接受了我分派到多个线程的机制之后?
    • 我会建议一种同步消息队列(例如带锁的 std::deque)。线程经常使违反直觉的事情发生,它实际上可能会减慢事情的速度。当存在 CPU 密集型代码(例如繁重的数学计算)时,线程很有用。
    • 他确实需要多个线程及时公平地从多个端口读取,除非他使用非阻塞 I/O,他没有提到。他没有说过任何关于瓶颈的事情。 UDP 中没有接受步骤。 -1
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-22
    • 1970-01-01
    • 2021-05-05
    • 1970-01-01
    • 1970-01-01
    • 2013-08-29
    • 1970-01-01
    相关资源
    最近更新 更多