Я новичок в программировании сокетов на С ++, и у меня есть проблема, которую я пытаюсь решить в течение некоторого времени.
Моя задача — обработать данные, полученные от двух разных датчиков. Я получаю данные через сокет 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;
}
Я был бы чрезвычайно признателен, если бы кто-то предложил, какова может быть настоящая проблема и каковы возможные способы ее решения. К сожалению, я не могу показать вам весь мой исходный код, так как я делаю это для своей работы, и мне не разрешено представлять его публично.
Пожалуйста, прости меня за недостаток знаний в этой области. Я охотно отвечу на все дополнительные вопросы.
Не вызывайте select () для каждого сокета отдельно. Установите выбор с обоими сокетами, а затем обработайте доступные данные (из одного или двух сокетов).
select
можно обрабатывать несколько розеток, поэтому используйте такой способ. Делать несколько recvfrom
на один цикл это неправильно. Вместо этого используйте select, чтобы выяснить, по какому сокету у вас есть данные, и по параметру remoteaddr выясните, откуда поступают эти данные.