Сокеты SOCK_STREAM наверняка сохраняют границы сообщений. Просто поместите каждое сообщение в отдельный поток: создайте новый сокет, подключите его, напишите сообщение, выключите его в направлении отправки, получите ответ и отключитесь. Затем повторите для следующего сообщения. То есть соединения поддерживают кадрирование, поскольку они четко определили сигнализацию «начало потока» и «конец потока»; они просто не поддерживают создание кадров в потоке. Так же, как сокеты SOCK_DGRAM не поддерживают кадрирование внутри дейтаграммы.

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

Я проверил параметры sysctl net.core.rmem_default, net.core.wmem_default, net.core.rmem_max, net.core.wmem_max и net.unix.max_dgram_qlen и увеличил их все, но они не имеют никакого эффекта, поскольку они имеют дело с общий размер буфера, а не размер сообщения.

Я также установил параметры сокетов SO_SNDBUF и SO_RCVBUF, но это та же проблема, что и выше. Размер буфера сокета по умолчанию устанавливается в зависимости от параметров сокета _default.

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

Максимальный размер на самом деле 130688? Если нет, то можно ли это изменить без перекомпиляции ядра?

Спасибо!

 Jaime19 янв. 2011 г., 14:49
Я согласен, что это возможно, это жесткий предел. Просто пытаюсь найти какое-то доказательство и, возможно, какое-то обоснование.
 Jon Trauntvein18 янв. 2011 г., 22:37
Это огромная датаграмма. По моему мнению, к тому времени, когда у вас будет такая дейтаграмма, вы, возможно, уже использовали TCP.
 JB.18 янв. 2011 г., 23:40
Я понял вашу точку зрения (и вопрос) лучше. Отредактировал запутанный комментарий и проголосовал; я буду исследовать все вокруг, если позволяет время, так как я также заинтересован в ответе.
 Jaime18 янв. 2011 г., 23:04
Да, это не помогает. Как я уже говорил в посте, он не позволит вам отправить сообщение более 130688 независимо от ваших настроек wmem. У меня их более 32 МБ, и я пробовал много комбинаций ниже этого.
 Jaime18 янв. 2011 г., 23:15
Просто чтобы добавить к этому. Это неправильное представление, что буферы отправки и буферы приема предназначены для отдельных сообщений. Буфер - это общий буфер ядра для всех сообщений. Параметры wmem и qlen sysctl фактически влияют на то, как и когда отправлять блоки. Поскольку буфер отправки заполняется (при условии, что никто не получает), когда общее количество байтов в буфере превысит размер буфера или общее число превысит qlen, send будет блокироваться.

Ответы на вопрос(1)

Решение Вопроса

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

udgc: page allocation failure. order:7, mode:0x44d0
[...snip...]
DMA: 185*4kB 69*8kB 34*16kB 27*32kB 11*64kB 1*128kB 1*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 3788kB
Normal: 13*4kB 6*8kB 100*16kB 62*32kB 24*64kB 10*128kB 0*256kB 1*512kB 0*1024kB 0*2048kB 0*4096kB = 7012kB
[...snip...]

unix_dgram_sendmsg() звонкиsock_alloc_send_skb() lxr1, который вызываетsock_alloc_send_pskb() с участиемdata_len = 0 иheader_len = размер датаграммыlxr2. sock_alloc_send_pskb() выделяетheader_len из "обычного" буферного пространства skbuff, иdata_len от разброса / сбора страницlxr3, Таким образом, похоже, что сокеты AF_UNIX не поддерживают разброс / сборку в текущем Linux.

 Jaime28 янв. 2011 г., 14:18
Превосходная работа. По сути, это то, что я нашел в своих следах, но вы указали реальную причину. Интересно, почему датаграммы имеют такой предел, а не потоки?
 ninjalj28 янв. 2011 г., 19:50
Сокеты SOCK_STREAM не сохраняют границы сообщений.
 Jonathan Ben-Avraham22 авг. 2014 г., 10:53
Смотрите также расширенный ответ наstackoverflow.com/questions/21856517/...
 Kaz07 мар. 2016 г., 16:54
Сокеты SOCK_STREAM наверняка сохраняют границы сообщений. Просто поместите каждое сообщение в отдельный поток: создайте новый сокет, подключите его, напишите сообщение, выключите его в направлении отправки, получите ответ и отключитесь. Затем повторите для следующего сообщения. То есть соединения поддерживают кадрирование, поскольку они четко определили сигнализацию «начало потока» и «конец потока»; они просто не поддерживают создание кадров в потоке. Так же, как сокеты SOCK_DGRAM не поддерживают кадрирование внутри дейтаграммы.

Ваш ответ на вопрос