Многопоточность для получения данных от нескольких клиентов 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 сокетов, и данные будут отправляться с интервалами в несколько миллисекунд одновременно. Здесь пакеты, полученные на каждом порту, имеют разный размер. Пакеты отправляются с заголовком и CRC. Является ли хорошей идеей иметь номера пакетов для отслеживания и повторного запроса потерянных пакетов?

(или) Какими способами можно отслеживать потерянные пакеты и запрашивать их с помощью UDP?


person m4n07    schedule 28.03.2013    source источник


Ответы (3)


Альтернативой потокам является функция select (), которая обеспечивает синхронное мультиплексирование ввода-вывода. Вы можете передать 5 файловых десктопов сокетов функции select () и дождаться, пока один из них не будет готов с данными. Промыть и повторить.

Взгляните на страницу руководства: http://linux.die.net/man/2/select или множество учебных пособий в Интернете.

person mvarshney    schedule 30.03.2013
comment
Спасибо. Фактически это 5 портов на каждого клиента. (10 клиентов * 5 = 50 сокетов). Каждый из 5 портов получает разные данные. После получения данных происходит некоторая запись ввода-вывода в файлы. - person m4n07; 05.04.2013

Вам не нужно несколько потоков.

Если ваше узкое место - ввод-вывод, потоки не помогут.

Если ваше узкое место - это обработка / ЦП, примите их все в одном потоке, а затем отправьте в несколько потоков.

person Pavel Radzivilovsky    schedule 28.03.2013
comment
Спасибо. Я еще не определил узкое место. Я думал, что, поскольку поток данных будет непрерывным, а данные будут отправляться каждые несколько миллисекунд, я думал, что смогу лучше справиться с использованием потоков. После принятия, каков механизм, при котором я отправляю в несколько потоков? - person m4n07; 29.03.2013
comment
Я бы предложил своего рода синхронизированную очередь сообщений (например, std :: deque с блокировкой). Потоки часто заставляют происходить противоречащие интуиции вещи, и это может фактически замедлить работу. Потоки полезны, когда есть код, интенсивно использующий ЦП, например, при выполнении сложных математических вычислений. - person Pavel Radzivilovsky; 29.03.2013
comment
Ему действительно нужно несколько потоков для своевременного и справедливого чтения с нескольких портов, если только он не использует неблокирующий ввод-вывод, о котором он не упомянул. Он ничего не сказал о узких местах. В UDP нет шага принятия. -1 - person user207421; 31.03.2013

если вам нужно решение потока для каждого порта: для каждого номера порта p создайте поток и передайте его в качестве параметра, тогда поток будет делать: socket (); bind (p), а (1) {recvfrom (); Отправить(); }

person bahaa    schedule 30.03.2013
comment
Спасибо, баха. Видя другие комментарии и синхронизацию потоков и т. Д., Я думаю о том, как лучше это сделать. - person m4n07; 30.03.2013