C ++ множественная обработка данных сокета UDP

Я новичок в программировании сокетов на С ++, и у меня есть проблема, которую я пытаюсь решить в течение некоторого времени.

Моя задача — обработать данные, полученные от двух разных датчиков. Я получаю данные через сокет UDP и затем обрабатываю пакет (очевидно, все это происходит в цикле while). Я использую данные для визуализации в реальном времени, поэтому весь процесс должен быть быстрым.

Все в порядке, пока я пытаюсь получить данные от одного датчика. Когда я хочу сделать это с двумя датчиками (и, следовательно, с двумя функциями recvfrom () в одном цикле), вот когда начинаются мои проблемы. Обработка действительно медленная, и поэтому я пропускаю некоторые пакеты. Мне известно, что функция recvfrom () является блокирующим вызовом, и я обработал ее с помощью функции select (), поэтому я знаю, что это не является источником проблемы.

Вот часть кода, которая, кажется, отвечает за суету:

 while (1)
{
SingleSocketReceiver(&socket_1, port_1, scene_1, ptrScene_1, model);
SingleSocketReceiver(&socket_2, port_2, scene_2, ptrScene_2, model);
}

Когда я комментирую вторую функцию SingleSocketReceiver (), все работает нормально.

А вот что включает в себя функция SingleSocketReceiver ():

int SingleSocketReceiver(UDPsocket* socket, uint16_t port,pcl::PointCloud<pcl::PointXYZ> scene, pcl::PointCloud<pcl::PointXYZ>::Ptr ptrScene,  pcl::PointCloud<pcl::PointXYZ>::Ptr model)

{

struct timeval tv;
fd_set rfds;

FD_ZERO(&rfds);
FD_SET(socket->pSocket,&rfds);

tv.tv_sec = 1;
tv.tv_usec = 0;

if ((socket->rc = select(FD_SETSIZE,&rfds,NULL,NULL,&tv)) < 0)
{
printf("Port No. %d: ERROR! - no data received!\n", port);
return RESULT_ERROR;
}

else if (socket->rc == 0)
{
printf("Port No. %d: Timeout - no data received!\n", port);
return RESULT_ERROR;

}
socket->rc=recvfrom(socket->pSocket,(char*)socket->udpPacketBuf,UDP_PACKET_BUF_LEN,0,&socket->remoteAddr,&socket->remoteAddrLen);

if(socket->rc==SOCKET_ERROR)
{
printf("Socket for port No.%d: Error in recvfrom\n", port);
return RESULT_ERROR;
}

else
{
// Check the packet counter for missing packets
if (socket->previous_packet_counter_valid)
{

if ((socket->ph->PacketCounter - socket->previous_packet_counter) != 1)
{
printf("Port No.%d: Packet Counter jumped from %u to %u (missing packets; try to redirect output)\n", port, socket->previous_packet_counter, socket->ph->PacketCounter);

socket->startOfChannelFound = 0;
}
}
socket->previous_packet_counter = socket->ph->PacketCounter;
socket->previous_packet_counter_valid = 1;
// is this the channel with our data?
if (socket->ph->ChannelID == socket->customerDataChannel)
{if (socket->ph->IndexOfPacketInChannel == 0)
{
socket->startOfChannelFound = 1;

if (socket->channel_buf_size == 0)
{
socket->channel_buf_size = socket->ph->TotalLengthOfChannel;
socket->channelBuf = (int8_t*) malloc(socket->channel_buf_size);
}

// as we reuse the buffer we clear it at the beginning of a transmission
memset(socket->channelBuf, 0, socket->channel_buf_size);
socket->pos_in_channel = 0;
}

if (socket->startOfChannelFound)
{
processPacket(socket->udpPacketBuf, socket->rc, socket->channelBuf, socket->channel_buf_size, &socket->pos_in_channel);

if (socket->ph->IndexOfPacketInChannel == socket->ph->NumberOfPacketsInChannel -1)
{processChannel8(socket->channelBuf, socket->pos_in_channel);
displayData();
createPointCloud(scene, ptrScene, model);
}
}
}
}
return RESULT_OK;

}

Я был бы чрезвычайно признателен, если бы кто-то предложил, какова может быть настоящая проблема и каковы возможные способы ее решения. К сожалению, я не могу показать вам весь мой исходный код, так как я делаю это для своей работы, и мне не разрешено представлять его публично.

Пожалуйста, прости меня за недостаток знаний в этой области. Я охотно отвечу на все дополнительные вопросы.

0

Решение

Не вызывайте select () для каждого сокета отдельно. Установите выбор с обоими сокетами, а затем обработайте доступные данные (из одного или двух сокетов).

1

Другие решения

select можно обрабатывать несколько розеток, поэтому используйте такой способ. Делать несколько recvfrom на один цикл это неправильно. Вместо этого используйте select, чтобы выяснить, по какому сокету у вас есть данные, и по параметру remoteaddr выясните, откуда поступают эти данные.

0