Як насправді працює "TIME_WAIT" на стороні сервера?


11

Я знаю, що в цьому питанні є досить багато питань, і я вважаю, що прочитав стільки з них, скільки це важливо, перш ніж прийти до цього питання.

Під "серверним TIME_WAIT" я маю на увазі стан пари роз'ємів на стороні сервера, яка ініціювала його закриття () на стороні сервера.

Я часто бачу ці твердження, які мені звучать суперечливо:

  1. Сторона сервера TIME_WAITнешкідлива
  2. Ви повинні розробити свої мережеві програми, щоб клієнти ініціювали закриття (), тому клієнт повинен мати це TIME_WAIT

Причиною, що я вважаю це суперечливим, є те, що TIME_WAITу клієнта може виникнути проблема - клієнт може вичерпати наявні порти, тому по суті вищесказане рекомендує перенести тягар TIME_WAITна сторону клієнта, де це може бути проблема, з стороні сервера, де це не проблема.

З боку клієнта, TIME_WAITзвичайно, є лише проблема для обмеженої кількості випадків використання. Більшість клієнт-серверних рішень залучають один сервер, і багато клієнтів, клієнти зазвичай не мають достатньо високого обсягу з'єднань, щоб це було проблемою, і навіть якщо вони є, існує ряд рекомендацій, щоб «нормально» ( на відміну від SO_LINGER0 тайм-ауту або втручання в систему tcp_tw sysctls) боротися зі стороною клієнта TIME_WAIT, уникаючи занадто швидкого створення з'єднань. Але це не завжди можливо, наприклад, для класів додатків, таких як:

  • системи моніторингу
  • генератори навантаження
  • проксі

З іншого боку, я навіть не розумію, наскільки серверна TIME_WAITдопомога взагалі. Причина TIME_WAITнавіть в тому, що вона запобігає впорскуванню несвіжих TCPфрагментів у потоки, до яких уже не належать. Для клієнта TIME_WAITце робиться просто неможливим створенням з'єднання з тими самими ip:portпарами, якими могло бути це несвіже з'єднання (використовувані пари заблоковані TIME_WAIT). Але для сервера це неможливо запобігти, оскільки локальна адреса матиме приймаючий порт, і завжди буде однаковою, а сервер не може (AFAIK, у мене є лише емпіричний доказ) заперечувати з'єднання просто тому, що вхідний аналог створив би ту саму адресу адреси, яка вже існує в таблиці сокетів.

Я написав програму, яка показує, що TIME-WAIT на стороні сервера ігнорується. Крім того, оскільки тест був виконаний на 127.0.0.1, ядро ​​повинно мати спеціальний біт, який навіть повідомляє йому, чи це серверна чи клієнтська сторона (оскільки в іншому випадку кортеж був би таким же).

Джерело: http://pastebin.com/5PWjkjEf , тестоване на Fedora 22, net config.

$ gcc -o rtest rtest.c -lpthread
$ ./rtest 44400 s # will do server-side close
Will initiate server close
... iterates ~20 times successfully
^C
$ ss -a|grep 44400
tcp    TIME-WAIT  0      0            127.0.0.1:44400         127.0.0.1:44401   
$ ./rtest 44500 c # will do client-side close
Will initiate client close
... runs once and then
connecting...
connect: Cannot assign requested address

Отже, на стороні сервера TIME_WAITз'єднання на тій самій самій парі можуть бути відновлені негайно та успішно, а на стороні клієнта - TIME-WAITна другій ітерації connect()справедливо не вдалося

Підводячи підсумок, питання складається в два рази:

  • Чи TIME_WAITнасправді сторона сервера нічого не робить, і залишається саме так, оскільки RFCвимагає цього?
  • Чи є причиною того, що клієнту рекомендується ініціювати close (), оскільки сервер TIME_WAITмарний?

Ви не будете закінчувати порти, якщо у вас не буде лише 1 клієнт. У вас є 65535 портів для кожної комбінації IP клієнт / сервер. З'єднання від 1.2.3.4:1111 відрізняється від 4.3.2.1:1111. Просто потрібно кілька байт пам'яті для кожного з'єднання в TIME_WAIT.
Marki555

Відповіді:


1

У серверній частині терміна TCP тут означає хост, який має сокет у стані LISTEN.

RFC1122 дозволяє сокету в режимі TIME-WAIT приймати нове з'єднання з деякими умовами

        When a connection is closed actively, it MUST linger in
        TIME-WAIT state for a time 2xMSL (Maximum Segment Lifetime).
        However, it MAY accept a new SYN from the remote TCP to
        reopen the connection directly from TIME-WAIT state, if it:

Точні відомості про умови див. У RFC1122 . Я б очікував, що на розетці також має бути відповідне пасивне ВІДКРИТТЕ (гніздо в стані LISTEN).

Активний OPEN (виклик підключення на стороні клієнта) не має такого винятку, і він повинен помилятися, коли сокет знаходиться в TIME-WAIT, згідно з RFC793 .

Моя здогадка щодо рекомендації щодо клієнта (в термінах TCP, який виконує активний OPEN, тобто підключення), ініційований близько, точно такий же, як і ваш, що в загальному випадку він поширює сокети TIME-WAIT на більше хостів, де є достатньо ресурсів для розетки. У звичайному випадку клієнти не надсилають SYN, який би повторно використовував сокети TIME-WAIT на сервері. Я погоджуюся, що застосовувати таку рекомендацію все ще залежить від випадку використання.


0

Це , мабуть, найяскравіший приклад того, що насправді TIME-WAIT робить, і ще важливіше, чому це важливо. Він також пояснює, чому слід уникати деяких "експертних" порад на машинах Linux, щоб "зменшити" ЧАС-ЧАС.


Досі не пояснюється, що відбувається, коли ініціюється підключення клієнт-сервер, і сервер має цю пару заблокований у TIME_WAIT
Pawel Veselov

Будь ласка, дивіться stackoverflow.com/questions/1490196/… - відповідь є те, що ви шукаєте.
Хушил

0

Сеанс tcp ідентифікується tupple (sourceIP, sourcePort, destIP, destPort). Отже, TIME_WAIT працює на кожному tcp-з'єднанні.

Що стосується сторони закриття, то в деяких сценаріях закриття з боку клієнта може зменшити TIME_WAIT розетки на сервері, тим самим трохи зменшивши пам'ять. У випадках, коли простір сокета може бути вичерпаний (через виснаження ефемерного порту) (наприклад, жадібні клієнти, що мають багато підключень до одного сервера), цю проблему слід вирішити в будь-якій стороні.


Будь ласка, поясніть; коли ви запитуєте, чи робить TW на стороні сервера що-небудь, вам цікаво, чи можна використовувати те саме з'єднання протягом періоду TW Відповідь ні, тому що з'єднання, визначене tupple, займає місце в таблиці tcp сервера. Якщо клієнт спробує відкрити те саме з'єднання незабаром, він отримає RST, ефективно відмовляючи від з'єднання tcp. До речі, стаття від Хушила є дуже описовою.
basos

Мені дуже шкода, ваша відповідь насправді відповідає на питання, я неправильно прочитав її та відмовився від мого коментаря. Однак це також здається невірним, оскільки у мене є код, який, схоже, підтверджує, що немає захисту від сервера TIME_WAIT(я оновив питання з цією інформацією). Посилання @ Хушила не охоплює TIME_WAITвипадки на стороні сервера досить детально.
Павло Веселов

-2

Ніколи не можна бути впевненим у ненадійному протоколі, що ви отримали останнє повідомлення від свого однорангового пристрою, тому небезпечно припускати, що ваш одноліток повісив телефон досить раптово. Основним недоліком протоколу TCP є те, що одночасно можуть бути відкриті лише 65000 або близько портів. Але способом подолати це було б перехід на серверну ферму, яка краще масштабується з навантаженням, ніж шляхом швидкої переробки номерів портів. В кінцевому підсумку клієнтів малоймовірно, що у вас не залишиться портів, якщо це основна робоча станція.


Мені дуже шкода, але це не відповідає на моє запитання.
Павло Веселов
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.