Настройка окна приема TCP в C и работа с tcpdump в Linux

Я использую Linux-систему 2.6.9-55.ELsmp, x86_64.

Я пытаюсь установить окно приема TCP с помощью функции setsockopt() с помощью C. Я пытаюсь сделать следующее:

rwnd = 1024;
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&rwnd, sizeof(rwnd));

Приведенный выше сегмент кода находится в клиентской программе, которая получает данные с сервера. Когда я запускаю программу для получения и наблюдения за выводом tcpdump, я наблюдаю за согласованием окна следующим образом:

11:34:40.257755 IP clientReceiver.42464 > serverSender.8991: 
S 1742042788:1742042788(0) win 5840 
<mss 1460,sackOK,timestamp 1688222886 0,nop,wscale 2>

Мы видим, что клиентская программа на самом деле согласовывает окно, отличное от того, которое я установил в клиентской программе. Однако из того, как я могу интерпретировать текст Стивена («TCP/IP Illustrated, Volume 1») Раздел 20.4, я полагаю, что вы влияете на то, на что он ссылается во второй блок-кавычке в Разделе 20.4, используя вызов setsockopt(), который я использую (см. выше). ).

Я хотел бы понять, где я ошибся.

Возможно, моя интерпретация того, что говорит Стивенс, неверна. В таком случае не могли бы вы указать мне правильный способ установки размера буфера приема? В качестве доказательства моего замешательства я ссылаюсь на справочную страницу Linux TCP-сокетов по адресу http://linux.die.net/man/7/tcp (см. комментарий к SO_RCFBUF).

Чего мне не хватает в этой истории? Как контролировать размер приемного буфера (и показывать его в выводе tcpdump)? Обратите внимание, что здесь я имею в виду настройку параметра сокета SO_RCFBUF — я понимаю, что это то, что отображается при согласовании окна в SYN.

Любой вклад приветствуется.


person Sonny    schedule 08.02.2010    source источник


Ответы (3)


Вам также нужно использовать TCP_WINDOW_CLAMP

rcvbuf = 2048;
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)& rcvbuf, sizeof(rcvbuf));
clamp = 1024;
setsockopt(sock, SOL_SOCKET, TCP_WINDOW_CLAMP, (char *)& clamp, sizeof(clamp));

Обратите внимание, что rcvbuf в два раза больше зажима, а может быть и больше. Вы можете разрешить автонастройку, оконный зажим все равно будет работать. Это не портативно.

person Andrew McGregor    schedule 08.02.2010
comment
Также обратите внимание, что минимальное ограничение ограничено половиной минимального RCVBUF (обычно 4096, поэтому минимальное ограничение обычно равно 2048). - person caf; 09.02.2010
comment
Я проверил это, и цифры на самом деле 256 и (таким образом) 128 для минимального устанавливаемого значения CLAMP соответственно. Проверьте код из tcp.c::setsockopt() в случае TCP_WINDOW_CLAMP и проверьте sock.h::#define SOCK_MIN_RCVBUF 256. Спасибо всем. Ваше здоровье! - person Sonny; 09.02.2010

Размер приемного буфера можно уменьшить только перед подключением сокета — увеличить его можно в любой момент. В каком порядке вы вызываете sockopt() по отношению к connect()?

person Community    schedule 08.02.2010
comment
Спасибо за быстрый ответ. Я вызываю setsockopt() перед подключением(). - person Sonny; 08.02.2010

Для TCP значение rwnd должно быть передано во время recv.

recv(носок, buf, rwnd, 0);

Это должно получить 1024 байта.

person bluegenetic    schedule 08.02.2010
comment
Привет, спасибо за ваш ответ. Из того, что я знаю, этот вызов recv() предназначен для приложения, то есть это скорость, с которой приложение потребляет предназначенный для него поток байтов. Другими словами, я не верю, что это окно приема, которое «i› согласовывается»/i› TCP в начале с узлом. - person Sonny; 08.02.2010
comment
Это размер буфера приложения, а не окно приема. Окно приема определяется размером буфера приема сокета за вычетом количества ожидающих данных в нем. - person user207421; 18.08.2015