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

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

Например:

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

... или...

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

Чувство кишки подсказывает мне, что базовый протокол делает это автоматически, с исправлением ошибок и т.д. Правильно ли это, или я должен перебивать мои данные?

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

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

Ответы

Ответ 1

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

Ответ 2

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

Ответ 3

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

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

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

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

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

Ответ 4

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

Ответ 5

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

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

Ответ 6

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

Ответ 7

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