Лучше отправить 1 большой кусок или много маленьких при использовании TCP? - PullRequest
13 голосов
/ 20 марта 2009

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

Например:

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

... или ...

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

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

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

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

Ответы [ 7 ]

19 голосов
/ 20 марта 2009

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

7 голосов
/ 20 марта 2009

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

6 голосов
/ 20 марта 2009

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

6 голосов
/ 20 марта 2009

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

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

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

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

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

3 голосов
/ 20 марта 2009

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

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

1 голос
/ 20 марта 2009

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

1 голос
/ 20 марта 2009

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

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