При использовании TCP лучше отправлять 1 большой кусок или много маленьких?

После того, как я accept() установил соединение, а затем write() к клиентскому сокету, лучше ли записывать все данные, которые вы собираетесь отправить, сразу или отправлять их порциями?

Например:

принять, написать 1МБ, отключить

…or…

принять, записать 256 байтов, записать 256 байтов,… n, отключить

Мое чутье подсказывает мне, что лежащий в основе протокол делает это автоматически, с исправлением ошибок и т. Д. Это правильно, или мне следует разбивать свои данные на части?

Прежде чем вы спросите, нет, я не уверен, откуда у меня возникла идея разбить данные - я думаю, это инстинкт, который я уловил при программировании веб-сервисов C # (чтобы обойти ограничения буфера приема и т. Д., Я думаю). Плохая привычка?

Примечание. Я использую C


person Nick Bolton    schedule 20.03.2009    source источник


Ответы (7)


Клиент и сервер будут разбивать ваши данные по своему усмотрению, поэтому вы можете отправить столько, сколько захотите, одним фрагментом. Посмотрите статью фон Велча в Руководстве пользователя по TCP Windows.

person Jon B    schedule 20.03.2009

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

person Paul Tomblin    schedule 20.03.2009
comment
Я видел в бесчисленных приложениях, что использование большего размера буфера всегда приводит к общей более высокой скорости передачи. Я также видел, что при использовании слишком большого размера буфера ваше приложение фактически будет передавать медленнее, потому что вы недостаточно быстро передаете данные в сокет. - person Brian R. Bondy; 20.03.2009
comment
@Brian, в нашем случае два объединенных пакета обычно были меньше одного пакета TCP / IP. - person Paul Tomblin; 20.03.2009

Алгоритм Нэгла, который обычно включен по умолчанию для сокетов TCP, скорее всего, объединит эти четыре 256 байт записываются в один и тот же пакет. Так что на самом деле не имеет значения, отправляете ли вы его как одну запись или несколько, в любом случае он должен оказаться в одном пакете. Отправка его как одного фрагмента имеет больше смысла, если у вас есть большой кусок для начала.

person Greg Rogers    schedule 20.03.2009
comment
На практике я всегда видел значительное увеличение скорости при использовании буфера большего размера. Возможно, это связано с копированием внутреннего буфера ОС, а не с TCP. - person Brian R. Bondy; 20.03.2009
comment
Что ж, для каждой отправки / записи, которую вы выполняете, вы должны переключать режим ядра, который составляет около 100 циклов. Так что, если вы делаете это очень часто, эти накладные расходы могут стать проблемой, и вы предпочтете делать все, что вам нужно, за один системный вызов. - person Greg Rogers; 20.03.2009

С уровня TCP, да, ваш большой буфер будет разделен, когда он слишком велик, и он будет объединен, когда он станет слишком маленьким.

На уровне приложения не позволяйте своему приложению иметь дело с неограниченными размерами буфера. На каком-то уровне их нужно разделить.

Если вы отправляете файл через сокет и, возможно, обрабатываете некоторые данные этого файла, например, сжимаете его. Затем вам нужно разделить это на части. В противном случае вы будете использовать слишком много ОЗУ, когда в конечном итоге столкнетесь с большим файлом, и ваша программа будет вне ОЗУ.

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

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

person Brian R. Bondy    schedule 20.03.2009
comment
Это хороший момент, особенно если приложение обрабатывает n байтов данных за раз. - person Jon B; 20.03.2009

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

Обычно я бы не стал изо всех сил разбивать записи, особенно не такие маленькие, как 256-байтовые куски. (Поскольку после накладных расходов TCP / IP в пакет Ethernet может поместиться примерно 1500 байтов, я бы использовал куски, по крайней мере, такого размера.)

person Dan Breslau    schedule 20.03.2009

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

person Chris Dale    schedule 20.03.2009
comment
TCP / IP не основан на модели oSI - person ; 20.03.2009
comment
модель OSI, хотя и неточна, все же полезна для описания сетевых протоколов. Стеки TCP / IP довольно хорошо отображаются в модели OSI вплоть до уровня TCP / UDP. Не следует путать модель OSI со стеком OSI stack, который никто не использует. - person Dan Breslau; 20.03.2009
comment
Нам придется не согласиться с полезностью неточной модели. - person ; 20.03.2009
comment
Эээ, вау, я неправильно понял здесь что-то очень простое? TCP находится на уровне 4 в модели OSI, в то время как IP находится на уровне 3. Собирая эти два вместе, мы получаем TCP / IP, который в наши дни используется для передачи данных по большинству сетей. - person Chris Dale; 20.03.2009
comment
Нет, OSI не повлияла на TCP / IP - доказательством того, что TCP / IP действительно работает. Тот факт, что вы можете сопоставить определенные биты TCP / IP с битами модели OSI, ничего не доказывает. - person ; 20.03.2009
comment
Хм, я всегда предполагал, что TCP / IP также был основан на модели OSI, согласно en .wikipedia.org / wiki / OSI_model # Comparison_with_TCP.2FIP это не так. Я думаю, каждый день узнавайте что-то новое ... - person Josh Weatherly; 20.03.2009

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

person Marko    schedule 20.03.2009