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

标签 c linux sockets network-programming udp

我想从不同的客户端接收数据(客户端数量是固定的,比如说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 请求它们?

最佳答案

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

查看手册页:http://linux.die.net/man/2/select或者网上有很多教程。

关于c - 多线程从多个UDP客户端接收数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15688078/

相关文章:

c - 如何在 C 中干净地终止线程?

android - 如何在我的共享库中包含正确的包含文件以使用 libdvm.so?

c - ANSI-C pow 函数和类型转换

c - 调用 open 时如何调用 sys_open 而不是 sys_openat

c++ - epoll反向代理在编写客户端时卡住

c - 真正换行 (LF) 的转义序列

C++(Unix): Open a text file with the default editor

php - 从url批量下载文件

c# - C# 中的一个非常简单的 TCP 服务器/客户端偶尔会丢弃数据包。我能做些什么来防止这种情况发生?

sockets - ZeroMQ:如何将消息发送到特定的订户