Подтвердить что ты не робот

Каков практический предел размера одного пакета, переданного через сокет домена?

Предположим, что существует сокет домена Unix, созданный для типичной сервер-клиентской программы. Клиент отправляет буфер 10 ГБ через сокет, и в то же время он потребляется сервером.

Разделяет ли ОС (Linux/BSD) буфер 10 ГБ на многие пакеты и отправляет/потребляет их или отправляется сразу?

Если невозможно отправить буфер 10 ГБ сокета домена за один раз, то каков размер практического размера для одного пакета?

Ограничения:

  • Программа будет работать как на Linux 2.6.32+, так и на FreeBSD 9 +
  • Размер отправляемого буфера составляет от 3 до 10 ГБ.
4b9b3361

Ответ 1

Существует ряд факторов, которые определяют максимальный размер пакета, который может быть отправлен в сокет Unix:

  • Параметр ядра максимального размера буфера отправки wmem_max, который определяет максимальный размер буфера отправки, который можно установить с помощью setsockopt (SO_SNDBUF). Текущую настройку можно прочитать с помощью /proc/sys/net/core/wmem_max и ее можно установить с помощью sysctl net.core.wmem_max=VALUE (добавьте параметр в /etc/sysctl.conf, чтобы изменения были постоянными при перезагрузках). Обратите внимание, что этот параметр применяется ко всем сокетам и протоколам сокетов, а не только к сокетам Unix.

  • Если несколько пакетов отправляются в сокет Unix (с использованием SOCK_DATAGRAM), то максимальный объем данных, которые могут быть отправлены без блокировки, зависит как от размера буфера отправки сокета (см. выше), так и от максимального количества непрочитанных пакетов в сокете Unix (параметр ядра net.unix.max_dgram_qlen).

  • Наконец, пакет (SOCK_DATAGRAM) требует непрерывной памяти (согласно Каков максимальный размер сообщения датаграммы AF_UNIX, которое можно отправить в Linux?), Сколько непрерывной памяти доступно в ядре, будет зависеть от многих факторов (например, нагрузки ввода-вывода в системе и т.д.).

Таким образом, чтобы максимизировать производительность вашего приложения, вам нужен большой размер буфера сокета (чтобы свести к минимуму изменения контекста контекста пользователя/ядра из-за системных вызовов сокета) и большой очереди сокетов Unix (чтобы разделить производителя и потребителя как насколько это возможно). Однако размер буфера отправки сокета и длина очереди не должны быть настолько большими, чтобы ядро ​​выходило из смежных областей памяти (что вызывало ошибки записи).

Фактические цифры будут зависеть от конфигурации и использования вашей системы. Вам нужно будет определить пределы путем тестирования... начните с wmem_max при 256 Кб и max_dgram_qlen в 32 и продолжайте удваивать wmem_max, пока не заметите, что все начинает ломаться. Вам нужно будет настроить max_dgram_qlen, чтобы сбалансировать активность производителя и потребителя в определенной степени (хотя, если производитель намного быстрее или намного медленнее, чем потребитель, размер очереди не будет иметь большого влияния).

Обратите внимание, что вашему производителю необходимо будет специально настроить размер буфера отправки сокетов на wmem_max байты с вызовом setsockopt (SO_SNDBUF) и ему придется разделить данные на wmem_max байтовые фрагменты (и потребитель должен будет их собрать).

Лучшее предположение: практические ограничения будут вокруг wmem_max ~ 8Mb и unix_dgram_qlen ~ 32.

Ответ 2

Нет никаких "пакетов" как таковых с сокетами домена. Семантика tcp "streams" или udp "датаграммы" - это своего рода симулированное w/i ядро, похожее на приложения для пользовательского пространства, но это касается того, насколько это возможно. Механизмы не связаны с сетевыми сокетами, использующими сетевые протоколы. Что вам действительно интересно здесь, так это то, насколько ядро ​​будет буферизировать вас.

С точки зрения вашей программы это не имеет большого значения. Подумайте о сокете как о трубе или FIFO. Когда буфер заполняется, вы собираетесь блокировать; если сокет не блокируется, вы получите короткие записи (предполагая потоки) или ошибку с EAGAIN. Это верно независимо от размера буфера. Однако вы должны иметь возможность запросить размер буфера с помощью getsockopt и увеличить его размер с помощью setsockopt, но я сомневаюсь, что вы собираетесь получить около 10 ГБ.

В качестве альтернативы вы можете посмотреть sendfile.

Ответ 3

Здесь есть две идеи. Один из них - размер отправленного пакета, если используется SOCK_DGRAM, а другой - размер буфера для сокета домена. Это зависит от переменных, заданных с помощью сокета домена. Размер может зависеть, если он является файловым сокетом памяти.

Ответ 4

Если вы говорите о SOCK_DGRAM, это легко определить с помощью эксперимента. Кажется гораздо более вероятным, что вы говорите о SOCK_STREAM, и в этом случае это просто не имеет значения. SOCK_STREAM сортирует внешний вид. Просто напишите все, что вам нравится: чем больше, тем лучше.