Буфер TCP memcpy возвращает мусорные данные, используя C ++ - PullRequest
0 голосов
/ 22 августа 2011

Я делаю что-то похожее на вопрос переполнения стека Обработка частичного возврата из TCP (recv) в C .

Полученные данные больше, чем инициализированный буфер (например, 1000 байт). Поэтому используется временный буфер большего размера (например, 10000 байт). Проблема в том, что полученные данные являются мусором. Я уже проверил смещение memcpy для временного буфера, но я продолжаю получать мусорные данные.

Этот пример показывает, что я делаю:

Первое полученное сообщение:

memcpy(tmpBuff, dataRecv, 1000);
offSet = offSet + 1000;

Второе сообщение вперед:

memcpy(tmpBuffer + offSet, dataRecv, 1000);

Есть что-то, что я должен проверить?


Я проверил гекс TCP, который был отправлен. Судя по всему, отправитель отправляет неполное сообщение. Моя программа работает так: когда отправитель отправляет сообщение, оно упаковывается (заголовок сообщения + фактическое сообщение). заголовок сообщения содержит некоторые метаданные, и одним из них является длина сообщения.

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

Если отправитель упаковывает три пакета в пакет, каждое сообщение имеет свой собственный заголовок сообщения, указывающий длину сообщения. Предположим, что все три сообщения имеют длину 300 байт каждое. Также предположим, что второе отправленное сообщение является неполным и получается только 100 байтов.

Когда получатель получает три сообщения в пакете, он вернет первое сообщение правильно. Поскольку второе сообщение является неполным, моя программа не будет знать, и поэтому она возвратит 100 байтов из второго сообщения и 200 байтов из третьего сообщения, поскольку заголовок сообщения указывает, что общий размер составляет 300 байтов. Таким образом, второе возвращенное сообщение будет содержать некоторые данные для мусора.

Что касается третьего сообщения, моя программа попытается получить длину сообщения из заголовка сообщения. Поскольку первые 200 байтов уже возвращены, заголовок сообщения недействителен. Таким образом, длина сообщения, возвращаемого моей программе, также будет мусором. Есть ли способ проверить полное сообщение?

1 Ответ

5 голосов
/ 22 августа 2011

Предположим, вы ожидаете 7000 байт по TCP-соединению.В этом случае весьма вероятно, что ваши сообщения будут разбиты на tcp-пакеты с фактическим размером полезной нагрузки, скажем, 1400 байт (то есть 5 сообщений).

В этом случае вполне возможны последовательные recv вызовыс целевым буфером в 1000 байт будет вести себя следующим образом:

recv -> reads 1000 bytes (packet 1)
recv -> reads 400 bytes (packet 1)
recv -> reads 1000 bytes (packet 2)
recv -> reads 400 bytes (packet 2)
...

Теперь, в этом случае, при чтении 400-байтового пакета вы все равно копируете полные 1000 байт в свой больший буфер, фактически вставляя 600 байтмусор между ними.Вы должны на самом деле только memcpy число полученных байтов, которое является возвращаемым значением самого recv.Конечно, вы также должны проверить, является ли это значение 0 (сокет закрыт) или меньше нуля (ошибка сокета).

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