2014-02-18 3 views
14

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

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

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

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

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

Нет ничего «типичного» в отношении клиента, который отправляет буфер 10 ГБ за один раз. Обычно он считывает некоторый источник в буфер, измеренный в KB, а не в GB, и отправляет его по частям. – EJP

+0

@EJP Знаете ли вы, сколько я должен разбить буфер 10 ГБ? Каждый 1GB/1MB? –

+0

Howard, какой тип вашего сокета? Как он был создан и как вы отправляете данные recv? – osgx

ответ

22

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

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

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

  3. Наконец, пакет (SOCK_DATAGRAM) требует непрерывной памяти (согласно What is the max size of AF_UNIX datagram message that can be sent in 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.

+0

Вы правы. Разбив буфер на части размером 128 КБ, я успешно передал более 1 ГБ буферизованных данных через сокет домена. Огромное спасибо. –

1

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

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

Кроме того, вы можете посмотреть sendfile.

+0

Спасибо, но я боюсь, что sendfile может не подходить для моего использования. В моем случае размер буфера сильно варьируется, варьируется от 3 байтов до 10 ГБ. –

+2

Поскольку вы отправляете другую программу на том же хосте, возможно, вам стоит просто отправить путь к файлу (если это файл на диске) и позволить другой программе прочитать его напрямую; или если это данные в ОЗУ, возможно, используйте mmap(), чтобы другая программа могла читать его напрямую из разделяемой памяти? –

+1

setsockopt с SO_SNDBUF ограничен sysctl_wmem_max (wmem_max sysctl) – osgx

0

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

-1

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

+1

EJP, http://en.wikipedia.org/wiki/Unix_domain_socket не является UDP или TCP. – osgx

Смежные вопросы