Как я могу узнать, что после первого вызова recv буфер чтения пуст или нет?Если оно не пустое, мне придется снова вызывать recv, но если я сделаю это, когда оно пустое, оно будет блокироваться на длительное время.
Вы можете использовать select
* 1007.* или poll
системные вызовы вместе с вашим дескриптором сокета, чтобы сказать, есть ли данные, ожидающие чтения из сокета.
Однако обычно должен быть согласованный протокол, которыйоба отправителя и получателя следуют, так что обе стороны знают, сколько данных должно быть передано.Например, возможно, отправитель сначала отправляет 2-байтовое целое число, указывающее количество байтов, которые он отправит.Затем получатель сначала читает это 2-байтовое целое число, чтобы узнать, сколько еще байтов нужно прочитать из сокета.
Независимо от того, как Тони указал ниже, надежное приложение должно использовать комбинацию информации о длинев заголовке, в сочетании с опросом сокета на предмет дополнительных данных перед каждым вызовом recv
(или с использованием неблокирующего сокета).Это предотвратит блокировку вашего приложения в том случае, если, например, вы знаете (из заголовка), что для чтения еще осталось 100 байт, но одноранговый узел не может отправить данные по какой-либо причине (возможно, компьютер-равноправный компьютер былнеожиданно отключается), в результате чего ваш recv
вызов блокируется.
Как я могу узнать, сколько байтов я скопировал в recv_buffer?Я не могу использовать strlen, потому что полученное сообщение может содержать нулевые байты.
Системный вызов recv
вернет число прочитанных байтов или -1, еслипроизошла ошибка.
На странице руководства для recv (2):
[recv] возвращает количество полученных байтов или -1, если произошла ошибка.Возвращаемое значение будет 0, когда узел выполнил упорядоченное завершение.