Как долго блокируется NetworkStream.Write() с небольшим размером TcpClient.SendBufferSize?

Как ведет себя метод NetworkStream.Write(), если я отправляю данные через NetworkStream TcpClient и TcpClient.SendBufferSize меньше данных?

документация MSDN для SendBufferSize говорит

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

Поэтому я знаю, что данные будут отправлены в несколько операций, и принимающий TCP-стек должен прозрачно собрать их в один непрерывный поток.

Но что именно происходит в моей программе за это время?

Если в SendBuffer достаточно места, TcpClient.GetStream().Write() вообще не будет блокироваться и вернется немедленно и так будет NetworkStream.Flush().

Если я установлю TcpClient.SendBufferSize на значение меньше, чем данные, Write() будет блокировать до тех пор, пока

  • либо первая часть данных была получена и подтверждена ACK,
  • или TcpClient.SendTimeout истек?

Или это работает как-то иначе? Действительно ли он ждет TCP ACK?

Есть ли какие-либо другие недостатки, помимо более высоких накладных расходов для такого меньшего размера буфера? Есть ли проблемы с изменением SendBufferSize на лету?

Пример:

byte[] data = new byte[20]    // 20 byte data
tcpClient.SendBufferSize= 10; // 10 byte buffer
tcpClient.SendTimeout = 1000; // 1s timeout

tcpClient.GetStream().Write(data,0,20); 
// will this block until the first 10 bytes have been full transmitted?
// does it block until a TCP ACK has been received? or something else?
// will it throw if the first 10 bytes have not been received in 1 second?
tcpClient.GetStream().Flush(); // would this make any difference?

Моя цель в основном состоит в том, чтобы лучше понять внутреннее устройство сети.

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

Если SentBuffer очень мал, будет ли ошибка обнаружена быстрее, если только она не произойдет в конце данных?

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


person HugoRune    schedule 03.06.2017    source источник
comment
Microsoft использует таймеры для перемещения данных из приложения в порт Ethernet. В основном с использованием событий тиков времени. Таким образом, весь размер буфера перемещается, даже если он не заполнен. Дейтаграммы TCP имеют максимальный размер ~ 1500 байт. Сообщения большего размера всегда разбиваются на дейтаграммы меньшего размера. Предоставленная вами ссылка предназначена для сетевого потока, и вы также можете отправлять TCP с помощью сокетов. Сетевой поток — это просто класс для добавления уровня потока в сокет tcp. Как я уже говорил ранее, потоковые классы в сети используют таймеры для очистки и заполнения, поэтому может быть некоторая задержка в зависимости от размера буферов, что приводит к неэффективности.   -  person jdweng    schedule 03.06.2017