Я пытаюсь понять, как окно приемника влияет на пропускную способность при соединении с высокой задержкой.
У меня есть простая пара клиент-серверных приложений на двух машинах, расположенных далеко друг от друга, с соединением между двумя RTT с задержкой 250 мс. Я провел этот тест как с Windows (XP, 7), так и с Linux (Ubuntu 10.x) с одинаковыми результатами, поэтому для простоты давайте предположим случай: Клиент получает данные: WinXP Pro Сервер отправляет данные: Win7 Pro Опять же, задержка составляет 250 мс RTT.
Я запускаю свой TCP-тест, не меняя размер буфера приемника на клиенте (по умолчанию 8 КБ), и вижу в сети (используя Wireshark):
- клиент отправляет ACKS на сервер, а пакеты TCP содержат RWIN=65k
- сервер отправляет данные и сообщает RWIN=65k
Глядя на трассировку, я вижу всплески из 3-4 пакетов (с полезной нагрузкой 1460 байт), сразу за которыми следует ACK, отправленный с клиентской машины на сервер, затем ничего в течение примерно 250 мс, затем новый пакет пакетов с сервера клиенту.
Итак, в заключение получается, что сервер не отправляет новые данные еще до того, как заполнит окно получателя.
Чтобы провести дополнительные тесты, я также провел тот же тест, на этот раз изменив размер буфера получателя на клиентской машине (в Windows изменение размера буфера получателя в конечном итоге влияет на RWIN, объявленный машиной). Я ожидаю увидеть большой пакет пакетов перед блокировкой для ACK... и, по крайней мере, более высокую пропускную способность.
В этом случае я установил размер буфера recv на 100 000 000. Пакеты от клиента к серверу теперь имеют RWIN=99 999 744 (ну, это хорошо), но, к сожалению, шаблон данных, отправляемых с сервера клиенту, остается прежним: короткий пакет с последующим долгим ожиданием. Чтобы подтвердить то, что я вижу в сети, я также измеряю время, необходимое для отправки порции данных с сервера клиенту. Я не вижу НИКАКИХ изменений в использовании большого RWIN или использовании по умолчанию.
Может ли кто-нибудь помочь мне понять, почему изменение RWIN на самом деле не влияет на пропускную способность?
Несколько замечаний: - сервер отправляет данные как можно быстрее, используя функцию записи () фрагментов по 8 КБ - как я уже говорил ранее, я наблюдаю аналогичные эффекты и при использовании Linux. изменение размера буфера приемника влияет на RWIN, используемый узлом, но пропускная способность остается прежней. - Я анализирую трассировку после нескольких сотен пакетов, чтобы дать механизму медленного старта TCP достаточно времени для увеличения размера CWIN.
Как и было предложено, я добавляю сюда небольшой снимок трассировки провода.
No. Time Source Destination Protocol Length Info
21 2.005080 CCC.CCC.CCC.CCC sss.sss.sss.sss TCP 60 57353 > 21500 [ACK] Seq=1 Ack=11681 Win=99999744 Len=0
22 2.005109 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=19305 Ack=1 Win=65536 Len=1460
23 2.005116 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=20765 Ack=1 Win=65536 Len=1460
24 2.005121 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=22225 Ack=1 Win=65536 Len=1460
25 2.005128 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 946 21500 > 57353 [PSH, ACK] Seq=23685 Ack=1 Win=65536 Len=892
26 2.005154 CCC.CCC.CCC.CCC sss.sss.sss.sss TCP 60 57353 > 21500 [ACK] Seq=1 Ack=14601 Win=99999744 Len=0
27 2.007106 CCC.CCC.CCC.CCC sss.sss.sss.sss TCP 60 57353 > 21500 [ACK] Seq=1 Ack=16385 Win=99999744 Len=0
28 2.007398 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=24577 Ack=1 Win=65536 Len=1460
29 2.007401 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=26037 Ack=1 Win=65536 Len=1460
30 2.007403 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=27497 Ack=1 Win=65536 Len=1460
31 2.007404 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=28957 Ack=1 Win=65536 Len=1460
32 2.007406 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=30417 Ack=1 Win=65536 Len=1460
33 2.007408 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 946 21500 > 57353 [PSH, ACK] Seq=31877 Ack=1 Win=65536 Len=892
34 2.007883 CCC.CCC.CCC.CCC sss.sss.sss.sss TCP 60 57353 > 21500 [ACK] Seq=1 Ack=19305 Win=99999744 Len=0
35 2.257143 CCC.CCC.CCC.CCC sss.sss.sss.sss TCP 60 57353 > 21500 [ACK] Seq=1 Ack=22225 Win=99999744 Len=0
36 2.257160 CCC.CCC.CCC.CCC sss.sss.sss.sss TCP 60 57353 > 21500 [ACK] Seq=1 Ack=24577 Win=99999744 Len=0
37 2.257358 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=32769 Ack=1 Win=65536 Len=1460
38 2.257362 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=34229 Ack=1 Win=65536 Len=1460
39 2.257364 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=35689 Ack=1 Win=65536 Len=1460
40 2.257365 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=37149 Ack=1 Win=65536 Len=1460
Как видите, сервер перестал отправлять данные на пакете №33.
Клиент отправляет ACK в пакете № 34 старого пакета (seq = 19305, отправлено в пакете № 20, здесь не показано). С RWIN 100 Мб я ожидаю, что сервер НЕ будет блокироваться какое-то время.
После 20-30 пакетов окно перегрузки на стороне сервера должно быть достаточно большим, чтобы отправить больше пакетов, чем я вижу... Я предполагаю, что окно перегрузки в конечном итоге вырастет до RWIN... но тем не менее, даже после сотни пакетов, шаблон тот же: данные данные затем блокируются на 250 мс...