Нулевое окно при отправке файлов через posix-сокеты - PullRequest
1 голос
/ 27 ноября 2009

У меня проблема - когда я пытаюсь отправить огромное количество данных через posix-сокеты (не важно, файлы это или какие-то данные), в какой-то момент я не получаю то, что ожидаю - я использовал wireshark для определить причину ошибки, и я обнаружил, что именно в тот момент, когда мое приложение разрывается, появляются пакеты, помеченные красным с надписью «нулевое окно» или «окно заполнено», отправленные в обоих направлениях.

В результате прикладной уровень не получает данные, отправленные функцией send (). Это получает следующую часть, хотя ...

Я что-то не так делаю?

РЕДАКТИРОВАТЬ:

Допустим, я хочу отправить 19232 фрагмента данных по 1024 байта каждый - в какую-то случайную точку (или не совсем) вместо 9344-го пакета, который я получаю 9345-м. И я не реализовал никакого протокола повторной передачи, потому что я думал, что TCP делает это для меня.

Ответы [ 4 ]

1 голос
/ 28 ноября 2009

Прежде всего, TCP является протоколом потока байтов, а не протоколом на основе пакетов. Тот факт, что вы отправили 1024-байтовый фрагмент, не означает, что он будет получен таким образом. Если вы заполняете канал достаточно быстро, чтобы получить нулевое условие окна (то есть, что больше нет места ни в буфере приема, ни в буфере отправки), то очень вероятно, что код получателя в какой-то момент сможет читать далеко больше, чем размер вашего "пакета".

Если вы специально не запрашивали неблокирующие сокеты, то и send, и recv будут блокироваться с нулевым состоянием окна / окна, а не возвращать ошибку.

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

1 голос
/ 28 ноября 2009

Zero Window / Window Full указывает, что один конец TCP-соединения не может получить больше данных, пока его клиентское приложение не прочитает некоторые данные, которые уже получены. Другими словами, это одна сторона соединения, говорящая другой стороне «не отправляйте больше данных, пока я не скажу вам иначе».

TCP обрабатывает повторные передачи. Вероятно, ваша проблема:

  1. Приложение на принимающей стороне недостаточно быстро читает данные.
  2. Это заставляет принимающий TCP сообщать о полном окне отправляющему TCP.
  3. Это, в свою очередь, заставляет send() на отправляющей стороне TCP возвращать либо 0 (без записи байтов), либо -1 с errno, установленным на EWOULDBLOCK.
  4. Ваше отправляющее приложение НЕ обнаруживает этот случай и предполагает, что send() отправил все данные, которые вы просили отправить.

Это приводит к потере данных. Вам необходимо исправить отправляющую сторону так, чтобы она обрабатывала send() с ошибками, включая возврат значения, меньшего, чем число байтов, которое вы просили его отправить. Если сокет неблокирующий, это означает, что ожидание до тех пор, пока select() не сообщит вам, что сокет доступен для записи, прежде чем пытаться снова.

0 голосов
/ 27 ноября 2009

Хм, из того, что я прочитал в Википедии , это может быть какое-то переполнение буфера (получатель сообщает об отсутствии окна приема). Просто предположение, хотя.

0 голосов
/ 27 ноября 2009

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

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