что происходит, когда tcp/udp сервер публикует быстрее, чем клиент использует?

Я пытаюсь разобраться с тем, что происходит, когда сервер публикует (по tcp, udp, и т.д.) быстрее, чем клиент может использовать данные.

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

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

Где я могу читать для получения деталей об этой теме? Я должен просто считать низкоуровневые детали TCP/UDP?

Спасибо

23
задан Shahbaz 4 January 2010 в 05:43
поделиться

6 ответов

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

В UDP такой системы управления потоком нет; в конце концов, она ненадежна. UDP стекам и на клиенте, и на сервере разрешено бросать датаграммы, если им так кажется, как и всем маршрутизаторам между ними. Если вы посылаете больше датаграмм, чем может доставить клиенту ссылка, или если ссылка доставляет больше датаграмм, чем может получить ваш клиентский код, то некоторые из них будут выброшены. Скорее всего, серверный и клиентский код никогда не узнает, если вы не построили какой-нибудь надежный протокол по сравнению с базовым UDP. Хотя на самом деле вы можете обнаружить, что датаграммы НЕ выбрасываются сетевым стеком, и что драйверы сетевых карт просто пережевывают весь доступный нестраничный пул и в конце концов приводят к аварийному завершению работы системы (см. эту запись в блоге для более подробной информации).

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

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

  • Если сервер использует не блокирующий ввод/вывод, то, скорее всего, вы получите возврат ошибки, говорящей о том, что вызов был бы заблокирован; вы можете делать и другие вещи, но ваш сервер должен будет переслать данные позднее...

  • Если вы используете асинхронный ввод/вывод, то все может быть более сложным. Например, при асинхронном вводе/выводе с использованием портов завершения ввода/вывода в Windows вы вообще не заметите ничего особенного. Ваши перекрывающиеся отправки все равно будут приняты, но вы можете заметить, что они занимают больше времени. Перекрывающиеся отправки ставятся в очередь на вашей машине сервера и используют память для ваших перекрывающихся буферов, а также, возможно, используют 'не-страничный пул'. Если вы продолжаете выпускать перекрывающиеся отправки, то вы рискуете израсходовать нестраничный пул памяти или использование потенциально неограниченного объема памяти в качестве буферов ввода/вывода. Поэтому при асинхронных входах/выходах и серверах, которые COULD генерируют данные быстрее, чем их клиенты могут их потреблять, вы должны написать свой собственный код управления потоком, который вы приводите в движение, используя завершения из записи. Я писал об этой проблеме в своем блоге здесь и здесь , и фреймворк моего сервера предоставляет код, который работает с ней автоматически для вас.

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

.
28
ответ дан 29 November 2019 в 02:16
поделиться

TCP имеет функцию управления потоком .

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

UDP, с другой стороны, совершенно другое. Сама UDP ничего подобного не делает и начинает выгружать данные, если они поступают быстрее, чем процесс может справиться. Приложение должно добавить логику в протокол приложения, если оно не может потерять данные (т.е. если ему нужен "надежный" поток данных)

.
5
ответ дан 29 November 2019 в 02:16
поделиться

Если Вы действительно хотите понять TCP, то Вам необходимо прочитать реализацию в сочетании с RFC; реальные реализации TCP не совсем соответствуют указанным. Например, в Linux есть концепция "давления на память", которая защищает от исчерпания пула DMA-памяти ядра (довольно маленького размера), а также предотвращает исчерпание буферного пространства одним сокетом любого другого.

.
2
ответ дан 29 November 2019 в 02:16
поделиться

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

.
1
ответ дан 29 November 2019 в 02:16
поделиться

С TCP этого не может произойти.

В случае UDP пакеты будут потеряны.

.
1
ответ дан 29 November 2019 в 02:16
поделиться

Статья Википедия TCP показывает формат заголовков TCP, в котором хранятся размер окна и номер последовательности квитирования. Остальные поля и описание там должны дать хорошее представление о том, как работает дросселирование передачи. RFC 793 определяет основные операции; на страницах 41 и 42 подробно описывается управление потоком.

.
0
ответ дан 29 November 2019 в 02:16
поделиться