Отправка буфера размером 10 МБ через сокет - фрагменты или целые 10 МБ?

Я преобразовываю детали, которые должны быть отправлены из моей функции C++, в Java в виде строк и в виде char*, которые будут отправлены через сокет.

Размер моего буфера составляет 10 МБ. Могу ли я отправить 10 МБ за один раз или мне следует разделить и отправить в виде кусков памяти меньшего размера?

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


person Sel_va    schedule 06.08.2015    source источник
comment
Это довольно субъективная вещь, зависящая от операционной системы и т. д.   -  person Sami Kuhmonen    schedule 06.08.2015
comment
Учитывая, что типичный MTU в Ethernet составляет 1500 байт, данные все равно будут разделены. Также я сомневаюсь, что какие-либо операционные системы имеют достаточно большие буферы, чтобы вместить все 10 МБ.   -  person Some programmer dude    schedule 06.08.2015
comment
что в этом случае делает ОС? Можете ли вы кратко ур мнение   -  person Sel_va    schedule 06.08.2015
comment
Вы можете взглянуть на это: en.wikipedia.org/wiki/OSI_model   -  person marstran    schedule 06.08.2015
comment
@JoachimPileborg: Вы предлагаете отправить 10 МБ целиком, так как данные все равно будут разделены?   -  person Sel_va    schedule 06.08.2015
comment
Пожалуйста, обратитесь к: [что происходит, когда я пишу данные в блокирующий сокет быстрее, чем читает другая сторона?] [1] [1]: stackoverflow. ком/вопросы/14241235/   -  person Murad Tagirov    schedule 06.08.2015
comment
Вы можете отправить его одним большим куском 10 МБ, однако будьте готовы к коротким записям, т.е. send() фактически отправляет меньше байтов, чем указано; вам придется зацикливаться в этом случае   -  person chill    schedule 06.08.2015
comment
@chill: какой максимальный размер куска я могу иметь?   -  person Sel_va    schedule 06.08.2015
comment
@RahulJain 2^31-1, наибольшее положительное целое число.   -  person user207421    schedule 06.08.2015
comment
@SamiKuhmonen Это не зависит ни от чего, кроме RFC и спецификации Posix.   -  person user207421    schedule 06.08.2015
comment
@EJP, как вы пришли к лимиту 2 ^ 31-1?   -  person chill    schedule 06.08.2015
comment
@chill Я уже ответил на это. «Наибольшее положительное целое число».   -  person user207421    schedule 06.08.2015
comment
@EJP, положительные целые числа бесконечны, наибольшего нет; Максимальное число, которое может быть представлено в size_t, которое является параметром send, содержащим длину буфера, или в ssize_t, которое является возвращаемым значением, зависит от платформы; довольно часто эти числа равны 2 ^ 64-1 или 2 ^ 63-1 соответственно.   -  person chill    schedule 06.08.2015
comment
@chill Блин, какая придирка. Я думаю, что мы можем не упоминать аксиомы Пеано, пока мы говорим о компьютерах.   -  person user207421    schedule 06.08.2015


Ответы (2)


Когда вы вызываете функцию write(), вы предоставляете буфер и количество байтов, которые хотите записать. Однако не гарантируется, что ОС отправит/запишет все байты, которые вы хотите записать, за один раз. (В случае блокирующих сокетов вызов write() будет блокироваться до тех пор, пока он не скопирует весь фрагмент в буфер TCP. Однако в случае неблокирующих сокетов функция write() вернется и не будет блокироваться, а запишет только те байты, которые она может).

Стек TCP/IP работает в ОС, и каждая ОС будет иметь свою собственную реализацию стека. Этот стек будет определять размеры буфера, и, кроме того, TCP/IP сам позаботится обо всей низкоуровневой статистике, такой как MSS, доступный размер окна получателя, что позволит TCP запускать алгоритмы управления потоком и управления перегрузкой.

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

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

person Sumit Trehan    schedule 06.08.2015
comment
Это гарантировано в режиме блокировки спецификацией Posix, за исключением редкого случая прерванного системного вызова. - person user207421; 06.08.2015
comment
Да... в неблокирующих сокетах количество записанных байтов может не совпадать с количеством байтов, которые мы хотим записать. Однако всегда полезно проверить, какой тип сокетов мы можем использовать. - person Sumit Trehan; 06.08.2015

Могу ли я отправить 10 МБ за один раз

да.

или я должен разделить и отправить как куски меньшей памяти?

No.

В чем разница между этими двумя подходами?

Разница в том, что в случае 1 вы позволяете TCP принимать все решения, в которых он хорош, со всеми дополнительными знаниями, которых у него нет, о MTU пути, RTT, окне приема на узле и т. д. .. тогда как в случае 2 вы пытаетесь выполнить за него работу TCP. Держите собаку и лайте сами.

Если я должен отправить как меньшую память, каков должен быть размер блока?

Как можно больше.

person user207421    schedule 06.08.2015
comment
@editor Если есть что-то не так с известным выражением «держать собаку и лаять на себя», это для меня новость. Пожалуйста, ограничьте свою деятельность реальными проблемами и оставьте в покое мой стиль прозы. - person user207421; 06.08.2015