TCP / IP передает полные сообщения? - PullRequest
2 голосов
/ 25 июня 2011

Я создаю библиотеку, которая поддерживает связь по сети между приложениями в c ++.Во время отладки я обнаружил, что некоторая информация, которую я получаю из сокета, кажется неполной.Крайне важно, чтобы эта информация была полной, потому что, если я расшифрую ее с помощью библиотеки буферов протокола, мне потребуется полное сообщение.

Это явление не является постоянным.Иногда я получаю все данные из сокета, иногда нет.Процедура тестирования выглядит следующим образом: запустить сервер, запустить клиент несколько раз.То, что я получаю, это вывод из функции receive(), который показывает, как меняются значения некоторых переменных.Одним из них является размер буфера, который я использую для хранения данных.Этот размер говорит мне, сколько данных находится в буфере.Клиенты отправляют два сообщения размером 3 (байты) - в этом конкретном тесте.Я ожидаю, что размер буфера будет кратен 3. Однако иногда размер равен 4 !.Это означает, что программа прочитала одно полное сообщение и 1/3 второго сообщения.Я не понимаю, почему я всегда получаю первое сообщение завершенным.В противном случае, protobuf завершит работу программы.

Я думал, что tcp / ip должен позаботиться о том, чтобы я получил полные сообщения.Моя проблема в том, что я не знаю размер заранее.Я ожидаю получить полное сообщение, чтобы я мог правильно его интерпретировать.

Ответы [ 2 ]

11 голосов
/ 25 июня 2011

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

2 голосов
/ 25 июня 2011

TCP разрешено фрагментировать ваши данные в несколько дейтаграмм , которые собираются по порядку у получателя. Вы гарантированно получите ваши данные в том порядке, в котором они были отправлены. Но некоторые данные, которые вы отправляете, могут поступить раньше, чем остальные.

Вы можете столкнуться с тем, что когда вы звоните receive, часть отправленных вами данных поступила на ваш компьютер, но некоторая их часть все еще отправляется по сети. Вам нужно будет буферизовать порции полученных вами данных и подождать, пока вы не получите полное «сообщение». Одним из способов справиться с этим является отправка записи фиксированной длины в начале каждого сообщения, которая кодирует длину оставшихся байтов в сообщении. Например, вы можете отправить 4-байтовую длинную без знака в сетевом порядке байтов, за которой следует такое количество байтов данных.

...