С гнездо для полной записи - PullRequest
0 голосов
/ 11 июня 2018

Руководство / учебное пособие Биджа по программированию сокетов дает готовый к использованию фрагмент при отправке всех данных через send.Он называется sendall и предоставляется здесь - http://beej.us/guide/bgnet/html/single/bgnet.html#sendall

Никаких таких четких указаний для recv не дано, даже если указано, что recv также может быть частичным.Почему?

Кроме того, как я пишу неблокирующую функцию recvall, аналогичную предложению sendall.Это похоже на FAQ, хотя простых ответов нет.

1 Ответ

0 голосов
/ 11 июня 2018

Ваша оригинальная идея не сработает.recv() будет блокироваться, если он прочитал все отправленные байты, если и до тех пор, пока не будут отправлены еще некоторые.Если никто не будет отправлен, вы застряли.Как указывалось выше, вам нужен какой-то способ узнать, когда вы достигли конца передачи.

Есть два пути, по которым вы могли бы пойти.Самый простой способ - просто закрыть сокет на отправляющей стороне, когда вы отправили все данные.recv() затем вернет 0 в должное время, и вы знаете, что все ожидаемые вами данные получены.

Другой, несколько более сложный способ - это отправить длину сообщения перед самим сообщением.Это достаточно просто.На отправляющей стороне (проверка ошибок для краткости опущена):

uint32_t msg_len = ...;
uint32_t network_byte_order_msg_len = htonl (msg_len);
int nbytes = sizeof (network_byte_order_msg_len);
sendall (skt, sizeof (uint32_t), &network_byte_order_msg_len, &nbytes);
nbytes = msglen;
sendall (skt, my_msg_buf, &nbytes);

И на принимающей стороне, предполагая, что у нас есть функция recv_bytes, которая вызывает в цикле recv, пока не получит количество байтовон ищет:

uint32_t network_byte_order_msg_len;
int nbytes = sizeof (network_byte_order_msg_len);
recv_bytes (skt, &network_byte_order_msg_len, nbytes);
int msg_len = ntohl (&network_byte_order_msg_len);
void *msg_buf = malloc (msg_len);
nbytes = msg_len;
recv_bytes (skt, msg_buf, &nbytes);

Обратите внимание, что, поступая таким образом, мы можем сразу же выделить в приемнике буфер сообщений правильного размера, что приятно и эффективно.

Вы в порядке, чтобы написать recv_bytes()?Отредактируйте реализацию в моем сообщении, если хотите, для будущих посетителей.

Редактировать: Этот код - C ++, я уверен, что вы можете это исправить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...