Эффект SO SNDBUF
Я не могу понять, как и почему работают следующие сегменты кода:
/* Now lets try to set the send buffer size to 5000 bytes */
size = 5000;
err = setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(int));
if (err != 0) {
printf("Unable to set send buffer size, continuing with default sizen");
}
если мы проверим значение буфера отправки, он действительно правильно установлен в 5000*2 = 10000. Однако, если мы попытаемся отправить больше, чем размер буфера отправки, это отправить все это. Например:
n = send(sockfd, buf, 30000, 0);
/* Lets check how much us actually sent */
printf("No. of bytes sent is %dn", n);
это печатает 30000.
как именно это работает? Разве тот факт, что размер буфера отправки был ограничен 10000, не имел никакого эффекта? Если да, то что именно? случилось? Какая-то фрагментация?
обновление: что произойдет, если сокет находится в неблокирующем режиме? Я попробовал следующее:
- изменение размера буфера до 10000 (5000*2) приводит к отправке 16384 байт
- изменение размера буфера до 20000 (10000*2) приводит к отправке 30000 байт
еще раз, почему?
2 ответов
задание SO_SNDBUF
опция отличается для TCP и UDP.
- для UDP это устанавливает ограничение на размер датаграммы, т. е. все, что крупнее, будет отброшен.
- для TCP это просто устанавливает размер буфера в ядре для данного сокета (с некоторым округлением до границы страницы и с верхним пределом).
поскольку похоже, что вы говорите о TCP, эффект, который вы наблюдаете, объясняется сокетом находясь в блокирующем режиме, так что send(2)
блокирует до тех пор, пока ядро не сможет принять все ваши данные и/или сетевой стек асинхронно де-очереди данных и толкая его на сетевую карту, тем самым освобождая пространство в буфере.
кроме того, TCP является потоковый протокол он не сохраняет никаких "сообщений" структуры. Один send(2)
может соответствовать несколько recv(2)
s на другой стороне, и наоборот. Рассматривайте его как byte-stream.
SO_SNDBUF настраивает буфер, который реализация сокета использует внутренне. Если ваш сокет не блокируется, вы можете отправить только до настроенного размера, если ваш сокет блокирует, нет ограничений для вашего вызова.