Меня тоже предложили задать здесь, поскольку конкретные вопросы о протоколах относятся к теме, но в случае, если кому-то интересно, за этот вопрос также есть небольшая награда за ServerFault.
Я читаю о потоке данных TCP, отложенном ACK и алгоритме Нэгла.
Пока я понимаю, что:
- Реализация отложенного ACK на TCP создает задержку при подтверждении полученных сегментов, чтобы дать приложению возможность записать некоторые данные вместе с подтверждением, тем самым избегая отправки пустого пакета ACK и способствуя перегрузке сети. .
- Реализация алгоритма Нэгла утверждает, что вы не можете отправить небольшой сегмент TCP, пока другой небольшой сегмент все еще не подтвержден. Это позволяет избежать загрузки трафика несколькими крошечными граммами.
В некоторых интерактивных приложениях, таких как Rlogin, например, алгоритм Нэгла и отложенные ACK могут "конфликтовать":
Rlogin отправляет ввод с клавиатуры на сервер, когда мы вводим их, и некоторые клавиши (например, F1) генерируют более одного байта (F1 = Escape + левая скобка + M). Эти байты могут быть отправлены в разных сегментах, если они доставляются в TCP один за другим.
Сервер не отвечает эхом до тех пор, пока не получит всю последовательность, поэтому все ACK будут задержаны (ожидая некоторых данных от приложения). С другой стороны, клиент будет ждать подтверждения первого байта перед отправкой следующего (соблюдая алгоритм Нэгла). Эта комбинация приводит к "медленному" Rlogin.
tcpdump
клавиш F1 и F2, отправляемых при Rlogin, представлен ниже:
type Fl key
1 0.0 slip.1023 > vangogh. login: P 1:2(1) ack 2
2 0.250520 (0.2505) vangogh.login > slip.1023: P 2:4(2) ack 2
3 0.251709 (0.0012) slip.1023 > vangogh.login: P 2:4(2) ack 4
4 0.490344 (0.2386) vangogh.login > slip.1023: P 4:6(2) ack 4
5 0.588694 (0.0984) slip.1023 > vangogh.login: . ack 6
type F2 key
6 2.836830 (2.2481) slip.1023 > vangogh.login: P 4:5(1) ack 6
7 3.132388 (0.2956) vangogh.login > slip.1023: P 6:8(2) ack 5
8 3.133573 (0.0012) slip.1023 > vangogh.login: P 5:7(2) ack 8
9 3.370346 (0.2368) vangogh.login > slip.1023: P 8:10(2) ack 7
10 3.388692 (0.0183) slip.1023 > vangogh.login: . ack 10
Теперь сомнения: несмотря на то, что на странице, которую я прочитал, говорится, что сервер не отвечает эхом до того, как он получит всю последовательность ключей, пакеты, захваченные через tcpdump
, показывают, что ключи отражаются в их соответствующих ACK (первый ответ - 2 байта, потому что эхо от ESC состоит из двух символов - каретка + левая скобка).
Если данные отправляются из приложения в TCP (эхо-ответ), почему задерживаются ACK? В соответствии с тем, что было сказано, о сервере ожидает полной последовательности, прежде чем повторить ее strong>, разве не предполагалось, что ACK не должны содержать эха до последнего ACK, который будет содержать эхо всей последовательности?
РЕДАКТИРОВАТЬ: Вот результат tcpdump
для измененного Rlogin без алгоритма Нэгла (флаг TCP_NODELAY):
type Fl key
1 0.0 slip.1023 > vangogh.login: P 1:2(1) ack 2
2 0.002163 (0.0022) slip.1023 > vangogh.login: P 2:3(1) ack 2
3 0.004218 (0.0021) slip.1023 > vangogh.login: P 3:4(1) ack 2
4 0.280621 (0.2764) vangogh.login > slip.1023: P 5:6(1) ack 4
5 0.281738 (0.0011) slip.1023 > vangogh.login: . ack 2
6 2.477561 (2.1958) vangogh.login > slip.1023: P 2:6(4) ack 4
7 2.478735 (0.0012) slip.1023 > vangogh.login: . ack 6
type F2 key
8 3.217023 (0.7383) slip.1023 > vangogh.login: P 4:5(1) ack 6
9 3.219165 (0.0021) slip.1023 > vangogh.login: P 5:6(1) ack 6
10 3.221688 (0.0025) slip.1023 > vangogh.login: P 6:7(1) ack 6
11 3.460626 (0.2389) vangogh.login > slip.1023: P 6:8(2) ack 5
12 3.489414 (0.0288) vangogh.login > slip.1023: P 8:10(2) ack 1
13 3.640356 (0.1509) slip.1023 > vangogh.login: . ack 10
В сегменте 4 можно заметить задержку ~ 0,2 мс, даже если алгоритм Нэгла выключен (поэтому все байты специальных ключей прибывают вместе и могут обрабатываться вместе). В сегменте 6 мы не можем идентифицировать задержку ~ 0,2 мс, потому что серверу требуется время для повторной обработки и повторной передачи некоторых потерянных сегментов, но эта задержка превышает 2 с.
В примере с клавишей F2 в сегменте 11 мы также можем заметить задержку ~ 0,2 мс. Мы не можем идентифицировать его в сегменте 12, потому что он, вероятно, был отправлен сразу после сегмента 11.
Это указывает на то, что ответ @MattTimmersans правильный, и, возможно, книга неверно интерпретирует задержку сегментов. Они действительно могут быть характеристикой сетевого носителя, а не задерживаться ACK из-за того, что данные не отправляются в стек TCP.
Ссылка: http://people.na.infn.it/~garufi/didattica/CorsoAcq/Trasp/Lezione9/tcpip_ill/tcp_int.htm