При отправке данных, превышающих SendBufferSize, как эти данные будут получены? - PullRequest
2 голосов
/ 23 июня 2010

Я только что задал вопрос о том, как отправлять данные больше, чем SendBufferSize, и я ответил, что это будет отправлено в нескольких частях.

Мой второй вопрос: как эти данные будут получены? Будет ли он завершен в сетевом потоке или будет разделен.

первый вопрос: Можете ли вы отправить файл, размер которого больше SendBufferSize, через TcpClient?

Ответы [ 5 ]

4 голосов
/ 14 октября 2014

TCP не только протокол сообщений. Это потоковый протокол, который заботится о разделении данных для нас. Позвольте мне перенести вас в основной раздел. В случае TCP существует две части: сегментация и фрагментация.

Сегментация происходит в TCP (транспортный уровень). Это зависит от двух параметров - MSS и размера окна. MSS определяет максимальный размер сегмента, который может принять устройство. MSS сообщается во время первоначального установления соединения через параметры TCP. Каждое направление потока данных может использовать разные MSS, и операционная система определяет их. Однако размер окна отправляется в заголовке TCP получателем, чтобы передать максимум данных, которые он может за один раз буферизовать на принимающей стороне соединения, прежде чем ожидать подтверждения и обновления окна от принимающего хоста. То есть хост может отправить несколько сегментов (коэффициент MSS) до исчерпания размера окна получателя.

Фрагментация происходит на IP (сетевой уровень) двумя способами. Если на пути связи между отправителем и получателем нет устройств с ограничением MTU, фрагментация будет соответствовать только MTU Ethernet (1500 байт). Однако в случае наличия промежуточного устройства с ограничением MTU между отправителем и получателем, уровень IP (Интернет-протокол) выполняет фрагментацию дейтаграммы, так что пакеты могут формироваться так, что они могут проходить через канал с меньшей максимальной единицей передачи ( MTU), чем исходный размер датаграммы. В случае промежуточного устройства с ограничениями MTU отправитель должен также развернуть обнаружение MTU пути, чтобы определить минимальный MTU в пути сети к приемнику и динамически настроить MSS, чтобы избежать фрагментации IP в сети. Определение MTU пути выполняется путем установки опции DF (Don't Fragment) в заголовках IP исходящих пакетов. Любое устройство на пути связи между отправителем и получателем, MTU которого меньше, чем пакет, будет отбрасывать такие пакеты и отвечать отправителю сообщением ICMP «Destination Unreachable (Datagram Too Big)», содержащим MTU устройства. Эта информация позволяет отправителю соответствующим образом уменьшить MTU предполагаемого пути.

Итак, это приводит к точке связи между MSS и MTU. RFC 791 гласит, что «все хосты должны быть готовы принимать дейтаграммы длиной до 576 октетов (независимо от того, прибывают ли они целыми или фрагментарно)». Итак, минимальный MTU для IP-сетей составляет 576. В случае TCP, вычитая 20 байтов для заголовка TCP и 20 байтов для заголовка IP, мы дадим нам 536 байтов в качестве стандартного MSS для TCP.

Теперь давайте перейдем к части повторной сборки. Фрагментация может происходить на основе MTU на промежуточных устройствах, но повторная сборка должна происходить только на целевом устройстве. TCP заботится о сегментации, однако на устройстве назначения TCP должен заботиться о порядке, но приложение должно заботиться о повторной сборке сегментов.

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

Если вы хотите иметь обмен сообщениями на основе сообщений, как в UDP, но в сочетании с функциями TCP, такими как надежная доставка по заказу, контроль перегрузки, а также дополнительными улучшениями / функциями, такими как многопотоковая передача, множественная передача , встроенное обнаружение MTU, тогда SCTP должен быть вашим выбором. Однако, если в вашей сети есть устаревшие системы NAT, вам может потребоваться инкапсуляция SCTP в UDP.

3 голосов
/ 18 сентября 2014

В отличие, например, от UDP, TCP не является протоколом, который позволяет отправлять отдельные «сообщения», которые доставляются получателю в той же форме.Вы скорее отправляете и получаете поток байтов.

В этом случае ваши данные разбиваются на IP-пакеты, независимо от из SendBufferSize, что, по умолчанию, равно 8192, что намного вышечем то, что вписывается в один IP-пакет (максимальный размер IP-пакета относится к MTU , но в основном чуть меньше 1500 байт).Пример:

  1. Socket.Send (2000 байт)
  2. IP-пакет № 1 (1460 байт)
  3. IP-пакет № 2 (540 байт)

Также: могут быть объединены данные нескольких Socket.Send() с ( алгоритм Нейгла ).Пример:

  1. Socket.Send (1000 байт)
  2. Socket.Send (1000 байт)
  3. IP-пакет № 1 (1460 байт)
  4. Пакет IP # 2 (540 байт)

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

Итог: с TCP вы не можете полагаться на получение пакетов с одинаковым номером и стакие же размеры, как они отправлены.Если вам это нужно, добавьте информацию о размере, как предлагает Стивен Клири, или используйте протокол, такой как UDP, или если вам нужна надежность: SCTP .Однако это выглядит излишним, если вы не заинтересованы в других улучшениях SCTP по сравнению с TCP.

2 голосов
/ 23 июня 2010

.Net обрабатывает разделение данных для вас. Вы можете писать и получать пакеты размером более SendBufferSize, не замечая этого (если вас не слишком беспокоит производительность).

1 голос
/ 23 июня 2010

Вам понадобится что-то под названием сообщение в рамке в вашем протоколе.

Интересный факт: вам это нужно, даже если вы отправляете сообщение меньше SendBufferSize.:)

0 голосов
/ 23 июня 2010

Скорее всего, ваши данные будут разделены при получении, поэтому вам нужно будет восстановить их после получения всех данных.

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