Мережеве програмування - TCP. Мережеве програмування - TCP Додаток tcp ip клієнт сервер

Клієнт-серверний додаток на потоковому сокеті TCP

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

Наступна програма створює сервер, який отримує запити на з'єднання від клієнтів. Сервер побудований синхронно, отже, виконання потоку блокується, поки сервер не дасть згоди на з'єднання з клієнтом. Ця програма демонструє простий сервер, який відповідає клієнту. Клієнт завершує з'єднання, відправляючи сервера повідомлення .

сервер TCP

Створення структури сервера показано на наступній функціональної діаграмі:

ось повний кодпрограми SocketServer.cs:

// SocketServer.cs using System; using System.Text; using System.Net; using System.Net.Sockets; namespace SocketServer (class Program (static void Main (string args) (// Встановлюємо для сокета локальну кінцеву точку IPHostEntry ipHost = Dns.GetHostEntry ( "localhost"); IPAddress ipAddr = ipHost.AddressList; IPEndPoint ipEndPoint = new IPEndPoint (ipAddr, 11000 ); // Створюємо сокет Tcp / Ip Socket sListener = new Socket (ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp); // Призначаємо сокет локальної кінцевій точці і слухаємо входять сокети try (sListener.Bind (ipEndPoint); sListener. Listen (10); // Починаємо слухати з'єднання while (true) (Console.WriteLine ( "Очікуємо з'єднання через порт (0)", ipEndPoint); // Програма призупиняється, чекаючи вхідні повідомлення Socket handler = sListener.Accept (); string data = null; // Ми дочекалися клієнта, намагається з нами з'єднатися byte bytes = new byte; int bytesRec = handler.Receive (bytes); data + = Encoding.UTF8.GetString (bytes, 0, bytesRec); // Показуємо дані на консолі Console.Write ( "Отриманий текст: "+ data +" \ n \ n "); // Відправляємо відповідь клієнту \ string reply = "Спасибі за запит в" + data.Length.ToString () + "символів"; byte msg = Encoding.UTF8.GetBytes (reply); handler.Send (msg); if (data.IndexOf ( " ")> -1) (Console.WriteLine (" Сервер завершив з'єднання з клієнтом. "); Break;) handler.Shutdown (SocketShutdown.Both); handler.Close ();)) catch (Exception ex) (Console.WriteLine (ex.ToString ());) finally (Console.ReadLine ();))))

Давайте розглянемо структуру даної програми.

Перший крок полягає у встановленні для сокета локальної кінцевої точки. Перш ніж відкривати сокет для очікування з'єднань, потрібно підготувати для нього адресу локальної кінцевої точки. Унікальний адресу для обслуговування TCP / IP визначається комбінацією IP-адреси хоста з номером порту обслуговування, яка створює кінцеву точку для обслуговування.

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

Створимо IPEndPoint для сервера, комбінуючи перший IP-адреса хост-комп'ютера, отриманий від методу Dns.Resolve (), з номером порту:

IPHostEntry ipHost = Dns.GetHostEntry ( "localhost"); IPAddress ipAddr = ipHost.AddressList; IPEndPoint ipEndPoint = new IPEndPoint (ipAddr, 11000);

Тут клас IPEndPoint представляє localhost на порту 11000. Далі новим екземпляром класу Socket створюємо потоковий сокет. Встановивши локальну кінцеву точку для очікування з'єднань, можна створити сокет:

Socket sListener = new Socket (ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

перерахування AddressFamilyвказує схеми адресації, які екземпляр класу Socket може використовувати для вирішення адреси.

У параметрі SocketTypeрозрізняються сокети TCP і UDP. У ньому можна визначити в тому числі такі значення:

Dgram

Підтримує дейтаграми. Значення Dgram вимагає вказати Udp для типу протоколу і InterNetwork в параметрі сімейства адрес.

Raw

Підтримує доступ до базового транспортного протоколу.

Stream

Підтримує потокові сокети. Значення Stream вимагає вказати Tcp для типу протоколу.

Третій і останній параметр визначає тип протоколу, необхідний для сокета. У параметрі РrotocolTypeможна вказати наступні найбільш важливі значення - Tcp, Udp, Ip, Raw.

Наступним кроком має бути призначення сокета за допомогою методу Bind (). Коли сокет відкривається конструктором, йому не призначається ім'я, а тільки резервується дескриптор. Для призначення імені сокету сервера викликається метод Bind (). Щоб сокет клієнта міг ідентифікувати потоковий сокет TCP, серверна програма повинна дати ім'я своєму сокету:

SListener.Bind (ipEndPoint);

Метод Bind () пов'язує сокет з локальною кінцевою точкою. Викликати метод Bind () треба до будь-яких спроб звернення до методів Listen () і Accept ().

Тепер, створивши сокет і зв'язавши з ним ім'я, можна слухати вхідні повідомлення, скориставшись методом Listen (). У стані прослуховування сокет чекатиме входять спроби з'єднання:

SListener.Listen (10);

У параметрі визначається заділ (backlog), Який вказує максимальне число з'єднань, які очікують обробки в черзі. У наведеному коді значення параметра допускає накопичення в черзі до десяти з'єднань.

У стані прослуховування треба бути готовим дати згоду на з'єднання з клієнтом, для чого використовується метод Accept (). За допомогою цього методу виходить з'єднання клієнта і завершується встановлення зв'язку імен клієнта і сервера. Метод Accept () блокує потік викликає програми до надходження сполуки.

Метод Accept () витягує з черги чекають запитів перший запит на з'єднання і створює для його обробки новий сокет. Хоча новий сокет створений, початковий сокет продовжує слухати і може використовуватися з багатопотокової обробкою для прийому декількох запитів на з'єднання від клієнтів. Ніяке серверний додаток не повинно закривати слухає сокет. Він повинен продовжувати працювати поряд з сокетами, створеними методом Accept для обробки вхідних запитів клієнтів.

While (true) (Console.WriteLine ( "Очікуємо з'єднання через порт (0)", ipEndPoint); // Програма призупиняється, чекаючи вхідні повідомлення Socket handler = sListener.Accept ();

Як тільки клієнт і сервер встановили між собою з'єднання, можна відправляти і отримувати повідомлення, використовуючи методи Send ()і Receive ()класу Socket.

Метод Send () записує вихідні дані сокету, з яким встановлено з'єднання. Метод Receive () зчитує вхідні дані в потоковий сокет. При використанні системи, заснованої на TCP, перед виконанням методів Send () і Receive () між сокетами має бути встановлено з'єднання. Точний протокол між двома взаємодіючими сутностями повинен бути визначений завчасно, щоб клієнтське і серверне додатки не блокували один одного, не знаючи, хто повинен відправити свої дані першим.

Коли обмін даними між сервером і клієнтом завершується, потрібно закрити з'єднання використовуючи методи Shutdown ()і Close ():

Handler.Shutdown (SocketShutdown.Both); handler.Close ();

SocketShutdown - це перерахування, що містить три значення для зупинки: Both- зупиняє відправку та отримання даних сокетом, Receive- зупиняє отримання даних сокетом і Send- зупиняє відправку даних сокетом.

Сокет закривається при виклику методу Close (), який також встановлює у властивості Connected сокета значення false.

Клієнт на TCP

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

Подорож по мережевим протоколам.

TCP і UDP - обидва протоколи транспортного рівня. UDP - це протокол без встановлення з'єднання і з негарантованої доставкою пакетів. TCP (Transmission Control Protocol) - це протокол із установленням з'єднання і з гарантованою доставкою пакетів. Спочатку відбувається рукостискання (Привіт. | Привіт. | Поболтаем? | Давай.), Після чого з'єднання вважається встановленим. Далі по цьому з'єднанню туди і назад надсилаються пакети (йде розмова), причому з перевіркою, чи дійшов пакет до одержувача. Якщо пакет загубився, або дійшов, але з битою контрольною сумою, то він надсилається повторно ( «повтори, не розчув»). Таким чином TCP більш надійний, але він складніше з точки зору реалізації і відповідно вимагає більше тактів / пам'яті, що має не останнє значення для мікроконтролерів. Як приклади прикладних протоколів, що використовують TCP, можна назвати FTP, HTTP, SMTP і багато інших.

TL; DR

HTTP (Hypertext Transfer Protocol) - прикладний протокол, за допомогою якого сервер віддає сторінки нашого браузеру. HTTP в даний час повсюдно використовується у Всесвітній павутинідля отримання інформації з веб-сайтів. На зображенні світильник на мікроконтролері з ОС на борту, в якому кольору задаються через браузер.

HTTP протокол текстовий і досить простий. Власне ось так виглядає метод GET, що посилається утилітою netcat на локальний IPv6 адресу сервера з лампочками:

~ $ Nc fe80 :: 200: e2ff: fe58: b66b% mazko 80<

Метод HTTP (англ. HTTP Method) зазвичай є коротке англійське слово, записане великими літерами, чутливе до регістру. Кожен сервер зобов'язаний підтримувати як мінімум методи GET і HEAD. Крім методів GET і HEAD, часто застосовується методи POST, PUT і DELETE. Метод GET використовується для запиту вмісту зазначеного ресурсу, в нашому випадку тут GET / b HTTP / 1.0 де шлях / b відповідає за колір (синій). Відповідь сервера:

HTTP / 1.0 200 OK Server: Contiki / 2.4 http://www.sics.se/contiki/ Connection: close Cache-Control: no-cache, no-store, must-revalidate Pragma: no-cache Expires: 0 Content- type: text / html Contiki RGB

Red is OFF

Green is OFF

Blue is ON

Код стану (у нас 200) є частиною першого рядка відповіді сервера. Він являє собою ціле число з трьох цифр. Перша цифра вказує на клас стану. За кодом відповіді зазвичай слід відокремлена пропуском пояснює фраза англійською мовою, яка роз'яснює людині причину саме такої відповіді. У нашому випадку сервер відпрацював без помилок, все пучком (ОК).

Як запит, так і відповідь містять заголовки (кожний рядок - окреме поле заголовка, пара ім'я-значення розділена двокрапкою). Закінчуються заголовки символом нового рядка, після чого можуть йти дані.

Мій браузер відмовляється відкривати локальний IPv6-адреса, тому в прошивці мікроконтролера прописаний додатковий адресу і такий же префікс також потрібно призначити віртуальному мережному інтерфейсу симулятора:

~ $ Sudo ip addr add abcd :: 1/64 dev mazko # linux ~ $ netsh interface ipv6 set address mazko abcd :: 1 # windows ~ $ curl http: //

TCP природним чином інтегрується в оточення клієнт / сервер (див. Рис. 10.1). серверний додаток прослуховує(Listen) надходять запити на з'єднання. Наприклад, служби WWW, пересилання файлів або доступу з терміналу прослуховують запити, що надходять від клієнтів. Комунікації в TCP запускаються відповідними подпрограммами, які і ініціалізують з'єднання з сервером (див. Главу 21 про програмному інтерфейсі socket).

Мал. 10.1.Клієнт викликає сервер.

Реально клієнт може бути іншим сервером. Наприклад, поштові сервери можуть з'єднуватися з іншими поштовими серверами для пересилання повідомлень електронної пошти між комп'ютерами.

10.2 Концепції TCP

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

10.2.1 Вхідний і вихідний потоки даних

концептуальнамодель з'єднання припускає пересилання додатком потоку даних рівному з додатком. У той же час воно здатне приймати потік даних від свого партнера по з'єднанню. TCP надає повнодуплексний(Full duplex) режим роботи, при якому одночасно обслуговуються два потокуданих (див. рис. 10.2).


Мал. 10.2.Додатки обмінюються потоками даних.

10.2.2 Сегменти

TCP може перетворювати виходить з програми потік даних в форму, придатну для розміщення в датаграму. Яким чином?

Додаток передає дані в TCP, а цей протокол поміщає їх в вихідний буфер(Send buffer). Далі TCP вирізає шматки даних з буфера і відправляє їх, додаючи заголовок (при цьому формуються сегменти- segment). На рис. 10.3 показано, як дані з вихідного буфера TCP пакетуються в сегменти. TCP передає сегмент в IP для доставки у вигляді окремої датаграми. Пакетування даних в шматки правильної довжини забезпечує ефективність їх пересилання, тому до створення сегмента TCP чекатиме, поки у вихідному буфері чи не з'явиться відповідне кількість даних.


Мал. 10.3Створення сегмента TCP

10.2.3 Виштовхування

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

Клієнтській програмі користувача потрібно, щоб TCP знав про пересилання даних на віддалений хост і виконав цю операцію негайно. У цьому випадку використовується виштовхування(Push).

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

10.2.4 Термінові дані

Модель пересилання даних додатком передбачає застосування упорядкованого потоку байтів, що прямує до точки призначення. Знову звернувшись наприклад інтерактивного сеансу, припустимо, що користувач натиснув клавішу attention(Увага) або break(Переривання). Віддалене додаток має бути здатне пропустити заважають байти і відреагувати на натискання клавіші якомога швидше.

механізм термінових даних(Urgent data) маркує спеціальну інформацію в сегменті як строкову.Цим TCP повідомляє свого партнера, що сегмент містить термінові дані, і може вказати, де вони знаходяться. Партнер повинен переслати цю інформацію в додаток призначення якомога швидше.

10.2.5 Порти додатки

Клієнт повинен ідентифікувати службу, до якої він хоче отримати доступ. Це виконується через специфікацію IP-адреси служби хоста і його номера порту TCP. Як і для UDP, номери портів TCP знаходяться в діапазоні від 0 до 65 535. Порти в діапазоні від 0 до 1023 називаються загальновідомими (well-known) і використовуються для доступу до стандартних службам.

Кілька прикладів загальновідомих портів і відповідних їм програм показано в таблиці 10.1. служби Discard(Порт 9) і chargen(Порт 19) є TCP-версіями вже відомих нам по UDP служб. Потрібно пам'ятати, що трафік на порт 9 протоколу TCP повністю ізольований від трафіку на порт 9 протоколу UDP.


Таблиця 10.1 Загальновідомі порти TCP і відповідні їм додатки

порт прикладна програма опис
9 Discard Скасування всіх вхідних даних
19 Chargen Генератор символів. Обмін потоком символів
20 FTP-Data Порт пересилання даних FTP
21 FTP Порт для діалогу FTP
23 TELNET Порт для віддаленої реєстрації по Telnet
25 SMTP Порт протоколу SMTP
110 POP3 Служба вибірки поштових повідомлень для персональних комп'ютерів
119 NNTP Доступ до мережевих новин

Що можна сказати про порти, які використовуються клієнтами? У рідкісних випадках клієнт працює не через загальновідомий порт. Але в таких ситуаціях, бажаючи відкрити з'єднання, він часто запитує у операційної системи присвоєння йому невикористаного і незарезервірованних порту. В кінці з'єднання клієнт зобов'язаний повернути цей порт назад, після чого порт може бути використаний повторно іншим клієнтом. Оскільки в пулі нерезервованих номерів існує більш 63 000 портів TCP, обмеження на порти для клієнтів можна не враховувати.

10.2.6 Адреси socket

Як ми вже знаємо, комбінація IP-адреси і порту для комунікації називається адресою socket.З'єднання TCP повністю ідентифікується адресою socket на кожному кінці даного з'єднання. На рис. 10.4 показано з'єднання між клієнтом з адресою socket (128.36.1.24, порт = 3358) і сервером з адресою socket (130.42.88.22, порт = 21).

Мал. 10.4.адреси socket

Заголовок кожної датаграми містить IP-адреси джерела і призначення. Надалі буде видно, що номери портів джерела і призначення вказуються в заголовку сегмента TCP.

Зазвичай сервер здатний одночасно керувати декількома клієнтами. Унікальні адреси socket сервера присвоюються одночасно всім його клієнтам (див. Рис. 10.5).


Мал. 10.5.Кілька клієнтів з'єднані з адресами socket сервера

Оскільки датаграмма містить сегмент з'єднання TCP, ідентифікує IP-адресами і портами, сервера дуже просто відстежувати кілька з'єднань з клієнтами.

10.3 Механізм забезпечення надійності TCP

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

10.3.1 Нумерація і підтвердження

Для забезпечення надійної пересилання даних в TCP використовуються нумерація (numbering) і підтвердження (acknowledgment - ACK). Схема нумерації TCP дещо незвична: коженпересилається по з'єднанню октеттакою, що має порядковий номер. Тема сегмента TCP містить порядковий номер першого октету даних цього сегмента.

Від приймача потрібне підтвердження отримання даних. Якщо ACK не спадає за інтервал тайм-ауту, дані передаються повторно. Цей спосіб називається позитивним підтвердженням з ретрансляцією(Positive acknowledgment with retransmission).

Одержувач даних TCP проводить строгий контроль входять порядкових номерів, щоб перевірити послідовність отримання даних і відсутність втрачених частин. Оскільки ACK випадковим чином може бути втрачений або затриманий, до одержувача можуть надійти дубльовані сегменти. Порядкові номери дозволяють визначити дублювання даних, які далі відкидаються.

На рис. 10.6 показаний спрощений погляд на тайм-аут і повторну пересилку в TCP.


Мал. 10.6.Тайм-аут і повторна пересилання в TCP

10.3.2 Поля портів, послідовності і ACK в заголовку TCP

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


Мал. 10.7.Початкові значення в полях заголовка TCP

Не можна не відзначити одну маленьку деталь. Припустимо, що TCP переслав байти від 1 до 50 і більше вже немає даних для відправки. Якщо від партнера надходять дані, TCP зобов'язаний підтвердити їх отримання, для чого пошле заголовок без підключених до нього даних. Природно, в цьому заголовку є параметр ACK. В поле послідовності - значення 51, тобто номер наступного байта, який має намірпослати TCP. Коли TCP пошле наступні дані, новий заголовок TCP також матиме в полі послідовності значення 51.

10.4 Установка з'єднання

Яким чином два додатки з'єднуються між собою? Перед комунікацією кожне з них викликає підпрограму для формування блоку пам'яті, який буде використаний для зберігання параметрів TCP і IP даного з'єднання, наприклад адрес socket, поточного порядкового номера, початкового значення часу життя і т.д.

Серверний додаток очікує появи клієнта, який, бажаючи отримати доступ до сервера, видає запит на з'єднання(Connect), що ідентифікує IP-адреса і порт сервера.

Існує одна технічна особливість. Кожна сторона починає нумерацію кожного байта ні з одиниці, а з випадкового порядкового номера(Далі ми дізнаємося, для чого це робиться). Вихідна специфікація дає пораду: початковий порядковий номер генерувати на основі 32-розрядної зовнішнього таймера, що збільшує значення приблизно кожні 4 мкс.

10.4.1 Сценарій з'єднання

Процедуру з'єднання часто називають потрійним рукостисканням (three-way handshake), оскільки для установки з'єднання проводиться обмін трьома повідомленнями - SYN, SYN і ACK.

Під час установки з'єднання партнери обмінюються трьома важливими порціями інформації:

1. Обсяг буферного простору для прийому даних

2. Максимальна кількість даних, переноситься у вхідному сегменті

3. Початковий порядковий номер, який використовується для вихідних даних

Відзначимо, що кожна зі сторін застосовує операції 1 і 2 для вказівки меж, в яких буде діяти інша сторона.Персональний комп'ютер може мати невеликий приймальний буфер, а суперкомп'ютер - величезний буфер. Структура пам'яті персонального комп'ютера може обмежувати надходять порції даних 1 Кбайт, а суперкомп'ютер управляється з великими сегментами.

Здатність управляти тим, як посилає дані інша сторона, є важливою властивістю, що забезпечує масштабованість TCP / IP.

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


Мал. 10.8.встановлення з'єднання

Виконуються наступні операції:

1. Сервер инициализируется і стає готовим до з'єднання з клієнтами (цей стан називається пасивним відкриттям - passive open).

2. Клієнт запитує у TCP відкриття з'єднання з сервером за вказаною IP-адресою і порту (цей стан називається активним відкриттям - active open).

3. Клієнтська TCP отримує початковий порядковий номер (в даному прикладі - 1000) і посилає сегмент синхронізації(Synchronize segment - SYN). У цьому сегменті пересилається порядковий номер, розмір приймального вікна (4 К) і розмір найбільшого сегмента, який може прийняти клієнт (1460 байт).

4. Коли надходить SYN, серверна TCP отримує свійпочатковий порядковий номер (3000). Вона посилає сегмент SYN, що містить початковий порядковий номер (3000), ACK 1001 (що означає нумерацію першого посланого клієнтом байта як 1001), розмір приймального вікна (4 К) і розмір найбільшого сегмента, який зможе отримати сервер (1024 байти).

5. Клієнтська TCP, отримавши від сервера повідомлення SYN / ACK, відсилає назад ACK 3001 (перший байт посланих сервером даних повинен нумеруватися як 3001).

6. Клієнтська TCP вказує свого додатком на відкриття з'єднання.

7. Серверна TCP, отримавши від клієнтської TCP повідомлення ACK, інформує свій додаток про відкриття з'єднання.

Клієнт і сервер анонсують свої правила для прийнятих даних, синхронізують свої порядкові номери і стають готовими до обміну даними. Специфікація TCP вирішує і інший сценарій (не дуже вдалий), коли рівні між собою програми одночасно виконують активну відкриття один одного.

10.4.2 Установка значень параметрів IP

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

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

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

10.5 Пересилання даних

Пересилання даних починається після завершення трехшаговий підтвердження створення з'єднання (див. Рис. 10.9). Стандарт TCP дозволяє включати в сегменти підтвердження звичайні дані, але вони не будуть доставлятися з додатком, поки створення з'єднання не завершиться. Для спрощення нумерації застосовуються 1000-байтниє повідомлення. Кожен сегмент заголовка TCP має поле ACK, що ідентифікує порядковий номер байта, який передбачається отримати від партнера по з'єднанню.


Мал. 10.9.Простий потік обміні даними і ACK

Перший посланий клієнтом сегмент містить байти від 1001 до 2000. У його полі ACK має перебувати значення 3001, що вказує порядковий номер байта, який передбачається отримати від сервера.

Сервер відповідає клієнту сегментом, що містить 1000 байт даних (що починаються з номера 3001). В його поле ACK заголовка TCP буде вказано, що байти з 1001 по 2000 вже успішно отримані, тому наступний очікуваний від клієнта порядковий номер сегмента повинен бути 2001.

Далі клієнт посилає сегменти, що починаються з байтів 2001, 3001 і 4001 в зазначеній послідовності. Відзначимо, що клієнт не очікує ACK після кожного з посланих сегментів. Дані пересилаються партнеру до заповнення його буферного простору (нижче ми побачимо, що одержувач може дуже точно вказати обсяг пересилаються йому даних).

Сервер економить пропускну здатність з'єднання, використовуючи єдиний ACK для вказівки успішності пересилання всіх сегментів.

На рис. 10.10 показана пересилання даних при втраті першого сегмента. По завершенні тайм-ауту пересилання сегмента повторюється. Відзначимо, що, отримавши втрачений сегмент, приймач відправляє один ACK, підтверджує пересилання обох сегментів.


Мал. 10.10.Втрата даних і повторна трансляція

10.6 Закриття з'єднання

Нормальне завершення з'єднання виконується за допомогою тієї ж процедури потрійного рукостискання, що і при відкритті з'єднання. Кожна зі сторін може почати закриття з'єднання за наступним сценарієм:

A:

B:"Добре".

В:"Я теж завершив роботу".

A:"Добре".

Припустимо і такий сценарій (хоча він використовується вкрай рідко):

A:"Я закінчив роботу. Даних для пересилання більше немає".

В:"Добре. Однак є якісь дані ..."

В:"Я теж завершив роботу".

A:"Добре".

У розглянутому нижче прикладі з'єднання закриває сервер, як це часто відбувається для зв'язків клієнт / сервер. В даному випадку після введення користувачем у сеансі telnetкоманди logout (вийти з системи) сервер ініціює запит на закриття з'єднання. У ситуації, показаної на рис. 10.11 діє таким чином:

1. Додаток на сервері вказує TCP на закриття з'єднання.

2. TCP сервера посилає заключний сегмент (Final Segment - FIN), інформуючи свого партнера про те, що даних для відправки більше немає.

3. TCP клієнта посилає ACK в сегменті FIN.

4. TCP клієнта повідомляє свого додатком, що сервер хоче закрити з'єднання.

5. Клієнтське додаток повідомляє своєму TCP про закриття з'єднання.

6. TCP клієнта посилає повідомлення FIN.

7. TCP сервера отримує FIN від клієнта і відповідає на нього повідомленням ACK.

8. TCP сервера вказує свого додатком на закриття з'єднання.


Мал. 10.11.закриття з'єднання

Обидві сторони можуть одночасно почати закриття. В цьому випадку звичайне закриття з'єднання завершується після відправки кожним з партнерів повідомлення ACK.

10.6.1 Раптове завершення

Кожна зі сторін може запросити раптове завершення (abrupt close) з'єднання. Це допустимо, коли додаток бажає завершити з'єднання або коли TCP виявляє серйозну комунікаційну проблему, яку не може дозволити власними коштами. Раптове завершення запитується посилкою партнеру одного або декількох повідомлень reset (скидання), що вказується певним прапорцем в заголовку TCP.

10.7 Управління потоком

Одержувач TCP завантажується надходять потоком даних і визначає, який обсяг інформації він зможе прийняти. Це обмеження впливає на відправника TCP. Представлене нижче пояснення даного механізму є концептуальним, і розробники можуть по-різному реалізувати його в своїх продуктах.

Під час установки з'єднання кожен з партнерів виділяє простір для вхідного буфера з'єднання і повідомляє про це протилежну сторону. Зазвичай обсяг буфера виражається цілим числом максимальних розмірів сегмента.

Потік даних надходить у вхідний буфер і зберігається в ньому до пересилання в додаток (яке визначається портом TCP). На рис. 10.12 показаний вхідний буфер, здатний прийняти 4 Кбайт.


Мал. 10.12.Приймальне вікно вхідного буфера

Буферне простір заповнюється в міру надходження даних. Коли додаток-одержувач забирає дані з буфера, що звільнилося місце стає доступним для нових даних, що надходять.

10.7.1 Приймальне вікно

приймальне вікно(Receive window) - будь-який простір у вхідному буфері, ще не зайняте даними. Дані залишаються у вхідному буфері, поки не будуть задіяні цільовим додатком. Чому програма не забирає дані відразу?

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

Приймальне вікно розширюється від останнього підтвердженого байта до кінця буфера. На рис. 10.12 спочатку доступний весь буфер і, отже, є приймальне вікно в 4 Кбайт. Коли надійде перший Кбайт, приймальне вікно скоротиться до 3 Кбайт (для простоти ми будемо вважати, що кожен сегмент має розмір в 1 Кбайт, хоча на практиці це значення змінюється в залежності від потреб додатка). Надходження наступних двох сегментів по 1 Кбайту призведе до скорочення приймального вікна до 1 Кбайта.

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

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

Що станеться, якщо надійшов сегмент можна розмістити в приймальному вікні, але він вчинив не по порядку? Зазвичай вважається, що всі реалізації зберігають дані, що надійшли в приймальному вікні і посилають підтвердження (ACK) тільки для цілого безперервного блоку з декількох сегментів. Це правильний спосіб, оскільки інакше при відкиданні даних, які прийшли не по порядку, істотно знизиться продуктивність.

10.7.2 Вікно відправки

Система, що передає дані, повинна відстежувати дві характеристики: скільки даних уже було відправлено і підтверджено, а також поточний розмір приймального вікна одержувача. активне простір відправки(Send space) розширюється від першого непідтвердженого октету до лівого краю поточного приймального вікна. частина вікна, яка використовується для відправки, Вказує, скільки ще додаткових даних можна послати партнеру.

Початковий порядковий номер і початковий розмір приймального вікна задаються під час встановлення з'єднання. Мал. 10.13 ілюструє деякі особливості механізму пересилання даних.

1. Вантажовідправник починає роботу з вікном відправки в 4 Кбайт.

2. Відправник пересилає 1 Кбайт. Копія цих даних зберігається до отримання підтвердження (ACK), оскільки може знадобитися їхня повторна передача.

3. Прибуває повідомлення ACK для першого Кбайта, і відправляються наступні 2 Кбайт даних. Результат показаний в третій зверху частини рис. 10.13. Зберігання 2 Кбайт триває.

4. Нарешті надходить ACK для всіх переданих даних (тобто всі вони отримані приймачем). ACK відновлює розмір вікна відправки в 4 Кбайт.

Мал. 10.13.вікно відправки

Слід вказати на кілька цікавих особливостей:

■ Відправник не чекає ACK для кожного з посилаються сегментів даних. Єдиним обмеженням на пересилку є розмір приймального вікна (наприклад, відправник повинен пересилати тільки 4 До однобайтових сегментів).

■ Припустимо, що відправник посилає дані в декількох дуже коротких сегментах (наприклад, по 80 байт). У цьому випадку дані можуть бути переформатовані для більш ефективної передачі (наприклад, в єдиний сегмент).

10.8 Тема TCP

На рис. 10.14 показаний формат сегмента (заголовок TCP і дані). Тема починається з ідентифікаторів портів джерела і призначення. Наступне далі поле порядкового номера(Sequence number) вказує позицію в вихідному потоці даних, яку займає даний сегмент. поле ACK(Підтвердження) містить відомості про передбачуваний наступному сегменті, який повинен з'явитися у вхідному потоці даних.


Мал. 10.14.сегмент TCP

Існують шість прапорів:

поле зміщення даних(Data Offset) містить розмір заголовка TCP в 32-розрядних словах. Тема TCP повинен закінчуватися на 32-бітної кордоні.

10.8.1 Варіант максимального розміру сегмента

параметр "Максимальний розмір сегмента"(Maximum segment size - MSS) застосовується для оголошення про найбільшому шматку даних, який може бути прийнятий і оброблений системою. Однак назва дещо неточно. Зазвичай в TCP сегментрозглядається як заголовок плюс дані. Однак максимальний розмір сегментавизначається як:

Розмір максимальної датаграми, яку можна прийняти, - 40

Іншими словами, MSS відображає найбільшу корисне навантаженняв приймальнику при довжині заголовків TCP і IP по 20 байт. Якщо є додаткові параметри, їх довжину слід відняти від загального розміру. Отже, кількість даних, які можна переслати в сегменті, визначається як:

Заявлений значення MSS + 40 - (сума довжин заголовків TCP і IP)

Зазвичай партнери обмінюються значеннями MSS в початкових повідомленнях SYN при відкритті з'єднання. Якщо система не анонсує величину максимального розміру сегмента, використовується значення за замовчуванням в 536 байт.

Розмір максимального сегмента кодується 2-байтовой вступною частиною з наступним далі 2-байтовий значенням, тобто найбільша величина становитиме 2 16 -1 (65 535 байт).

MSS накладає жорсткі обмеження на пересилаються в TCP дані: приймач не зможе обробити великі значення. Однак відправник використовує сегменти меншого розміру,оскільки для з'єднання визначається ще розмір MTU по шляху проходження.

10.8.2 Використання полів заголовка в запиті на з'єднання

Перший сегмент, що посилається для відкриття з'єднання, має значення прапора SYN, рівне 1, і прапора ACK - 0. Початковий SYN є єдинимсегментом, мають поле ACK зі значенням 0. Відзначимо, що засоби захисту користуються цією ознакою для виявлення вхідних запитів на сеанс TCP.

поле порядкового номерамістить початковий порядковий номер(Initial sequence number), поле вікна -початковий розмір приймального вікна.Єдиним певним на сьогоднішній момент параметром TCP є максимальний розмір сегмента (коли він не вказаний, використовується значення за замовчуванням в 536 байт), який передбачає отримувати TCP. Це значення займає 32 біта і зазвичай присутній в запиті на з'єднання в поле варіантів(Option). Довжина заголовка TCP, що містить значення MSS, становить 24 байта.

10.8.3 Використання полів заголовка у відповіді на запит з'єднання

У дозвільному відповіді на запит з'єднання обидва прапора (SYN і ACK) рівні 1. Відповідає система вказує початковий порядковий номер у відповідному полі, а розмір приймального вікна - в поле Window. Максимальний розмір сегмента, який бажає використовувати одержувач, зазвичай знаходиться у відповіді на запит про з'єднання (в поле варіантів). Це значення може відрізнятися від значення запитуючої з'єднання боку, тобто можуть застосовуватися дві різні величини.

Запит на з'єднання може бути відхилений за допомогою вказівки у відповіді прапора скидання (RST) зі значенням 1.

10.8.4 Вибір початкового порядкового номера

Специфікація TCP передбачає, що під час установки з'єднання кожна зі сторін вибирає початковий порядковий номер(За поточним значенням 32-розрядної внутрішнього таймера). Як це виконується?

Уявімо, що станеться у випадку краху системи. Припустимо, що користувач відкрив з'єднання якраз перед крахом і відправив невелику кількість даних. Після відновлення система вже не пам'ятає нічого з того, що робилося перед крахом, включаючи вже запущені з'єднання і привласнені номери портів. Користувач повторно встановлює з'єднання. Номери портів не збігаються з початковими привласнення, і деякі з них, можливо, вже використовуються іншими сполуками, встановленими за кілька секунд до краху.

Тому інша сторона в самому кінці з'єднання може не знати про те, що її партнер пройшов через крах і його робота потім була відновлена. Все це призведе до серйозних збоїв в роботі, особливо коли проходить довгий час, поки старі дані не пройдуть по мережі і не змішаються з даними від новоствореного з'єднання. Вибір за таймером старту з оновленням (fresh start) дозволяє виключити подібні проблеми. Старі дані будуть мати іншу нумерацію, ніж діапазон порядкових номерів нового з'єднання. Хакери при фальсифікації IP-адреси джерела для довірчого хоста намагаються отримати доступ до комп'ютерів за допомогою вказівки в повідомленні передбачуваного початкового порядкового номера. Криптографічний функція хешування на основі внутрішніх ключів служить найкращим способом для вибору захищених початкових номерів.

10.8.5 Загальноприйнята використання полів

При підготовці заголовка TCP до пересилання порядковий номер першого октету даних, що передаються вказується в полі послідовного номера(Sequence Number).

Номер наступного октету, очікуваного від партнера по з'єднанню, заноситься в поле підтвердження(Acknowledgment Number) при установці біта ACK в 1. Поле вікна(Window) призначене для поточного розміру приймального вікна. У цьому полі міститься кількість байтів від номера підтвердження, яке можна прийняти. Відзначимо, що це значення дозволяє точно керувати потоком даних. За допомогою цього значення партнер вказує реальний стан приймального вікна протягом сеансу обміну.

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

Прапор URGENT (терміновість) при значенні 1 передбачає термінову пересилання даних, а відповідний покажчик повинен посилатися на останній октет термінових даних. Типовим використанням термінових даних є пересилання з терміналу сигналів на скасування або переривання.

Термінові дані часто називають інформацією поза смуги пропускання(Out-of-band). Однак цей термін неточний. Термінові дані пересилаються в звичайному потоці TCP, хоча окремі реалізації можуть мати спеціальні механізми для вказівки з додатком на надходження термінових даних, а додаток має перевірити вміст термінових даних, перш ніж надійдуть всі байти повідомлення.

Прапор RESET (скидання) має значення 1, коли слід аварійно завершити з'єднання. Цей же прапор встановлюється у відповіді під час вступу сегмента, не пов'язаного ні з одним з поточних з'єднань TCP.

Прапор FIN встановлюється в 1 для повідомлень про закриття з'єднання.


10.8.6 Контрольна сума

Контрольна сума IP призначена тільки для заголовка IP, а контрольна сума TCP обчислюється для всього сегмента, а також для псевдозаголовка, створеного з заголовка IP. Під час обчислення контрольної суми TCP відповідне поле має значення 0. На рис. 10.15 показаний псевдозаголовок, дуже нагадує той, що використовується в контрольній сумі UDP.


Мал. 10.15.Поле псевдозаголовка включається в контрольну суму TCP

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

10.9 Приклад сегмента TCP

Мал. 10.16, протокол роботи аналізатора Snifferкомпанії Network General, являє собою послідовність сегментів TCP. Перші три сегменти встановлюють з'єднання між клієнтом і сервером Telnet. В останньому сегменті переноситься 12 байт даних.


Мал. 10.16.Відображення заголовка TCP аналізатором Sniffer

аналізатор Snifferтранслює більшість значень в десятковий вигляд. Однак значення прапорів виводяться як шістнадцяткові. Прапор із значенням 12 являє собою 010010. Контрольна сума виводиться теж в шістнадцятковому вигляді.

10.10 Підтримка роботи сеансу

10.10.1 Зондування вікна

Швидкісний відправник і повільний одержувач можуть сформувати приймальне вікно розміром в 0 байт. Цей результат називається закриттям вікна(Close window). Коли з'являється вільне місце для поновлення розміру приймального вікна, використовується ACK. Однак, якщо таке повідомлення буде втрачено, обидві сторони повинні будуть очікувати до нескінченності.

Для уникнення такої ситуації відправник встановлює зберігається таймер(Persist timer) при закритті пребагато вікна. Значним таймера береться тайм-аут повторної пересилки. По завершенні роботи таймера партнеру відсилається сегмент зондування вікна(Window probe; в деяких реалізаціях в нього включаються і дані). Зондування змушує партнера посилати назад ACK, який повідомляє про поточний статус вікна.

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

10.11 Завершення сеансу

10.11.1 Тайм-аут

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

Досягнувши першого порогового значення для повторної пересилки (ретрансляції), TCP вказує IP на необхідність перевірки відмовив маршрутизатора і одночасно інформує додаток про проблему. TCP продовжує пересилання даних, поки не буде досягти другого граничне значення, і тільки після цього розриває з'єднання.

Зрозуміло, перед тим як це станеться, може надійти повідомлення ICMP про недосяжність точки призначення з якихось причин. У деяких реалізаціях навіть після цього TCP продовжить спроби доступу до точки призначення до завершення інтервалу тайм-ауту (після чого проблема може бути зафіксована). Далі з додатком повідомляється про недосяжність точки призначення.

Додаток може встановити власний тайм-аут на доставку даних і проводити власні операції при завершенні цього інтервалу. Зазвичай проводиться призвести до втрати з'єднання.

10.11.2 Підтримка з'єднання

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

Однак будь-яке з'єднання - активне або неактивне - займає багато пам'яті комп'ютера. Деяким адміністраторам потрібно повернути в системи невикористані ресурси. Тому багато реалізації TCP здатні посилати повідомлення про підтримці з'єднання(Keep-alive), тестуючі неактивні сполуки. Такі повідомлення періодично відправляються партнеру для перевірки його існування в мережі. У відповідь повинні надходити повідомлення ACK. Використання повідомлень про підтримку з'єднання не є обов'язковим. Якщо в системі є така можливість, додаток може скасувати її власними коштами. передбачуваний період за замовчуваннямдля тайм-ауту підтримки з'єднання становить цілих дві години!

Згадаймо, що додаток може встановити власний таймер, по якому на своєму рівні і буде приймати рішення про завершення з'єднання.

10.12 продуктивність

Наскільки ефективна робота TCP? На продуктивність ресурсів впливають багато факторів, з яких основними є пам'ять і смуга пропускання (див. Рис. 10.17).


Мал. 10.17.Фактори продуктивності TCP

Смуга пропускання і затримки в використовуваної фізичної мережі істотно обмежують пропускну здатність. Погана якість пересилання даних призводить до великого обсягу відкинутих датаграмм, що викликає повторну пересилку і, як наслідок, знижує ефективність смуги пропускання.

Приймальна сторона повинна забезпечити достатнє буферний простір, що дозволяє відправнику виконувати пересилання даних без пауз в роботі. Це особливо важливо для мереж з великими затримками, в яких між відправкою даних і отриманням ACK (а також при узгодженні розміру вікна) проходить великий інтервал часу. Для підтримки стійкого потоку даних від джерела приймаюча сторона повинна мати вікно розміром не менше ніж твір смуги пропускання на затримку.

Наприклад, якщо джерело може відсилати дані зі швидкістю 10 000 байт / с, а на повернення ACK витрачається 2 с, то на іншій стороні потрібно забезпечити приймальне вікно розміром не менше 20 000 байт, інакше потік даних не буде безперервним. Приймальний буфер в 10 000 байт вполовину знизить пропускну здатність.

Ще одним важливим фактором для продуктивності є здатність хоста реагувати на високопріоритетні події і швидко виконувати контекстне перемикання, Тобто завершувати одні операції і перемикатися на інші. Хост може інтерактивно підтримувати безліч локальних користувачів, пакетні фонові процеси і десятки одночасних комунікаційних з'єднань. Контекстне перемикання дозволяє обслуговувати всі ці операції, приховуючи навантаження на систему. Реалізації, в яких проведена інтеграція TCP / IP з ядром операційної системи, можуть істотно знизити навантаження від використання контекстного перемикання.

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

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

Припустимо, що мережеве оточення абсолютно: є достатні ресурси і контекстне перемикання виконується швидше, ніж ковбої вихоплюють свої револьвери. Чи буде отримана прекрасна продуктивність?

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

Не менш важливо виняток і застосування алгоритмів Джекобсон, Керна і Партриджа (ці цікаві алгоритми будуть розглянуті нижче).

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

10.13 Алгоритми підвищення продуктивності

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

повільний старт(Slow start) заважає використанню великої частки мережевого трафіку для нового сеансу, що може привести до непродуктивних втрат.

■ Лікування від синдрому "нетямущого вікна"(Silly window syndrome) оберігає погано розроблені додатки від перевантаження мережі повідомленнями.

затриманий ACK(Delayed ACK) знижує перевантаження за допомогою скорочення кількості незалежних повідомлень підтвердження пересилання даних.

Обчислюваний тайм-аут повторної пересилки(Computing retransmission timeout) грунтується на узгодженні реального часу сеансу, зменшуючи обсяг непотрібних повторних пересилань, але при цьому не викликає великих затримок для реально необхідних обмінів даними.

■ Гальмування пересилання TCP при перевантаженняхв мережі дозволяє маршрутизаторів повернутися в початковий режим і спільно використовувати мережеві ресурси для всіх сеансів.

■ Відправка дубльованих ACK(Duplicate ACK) при отриманні сегмента поза послідовності відправки дозволяє партнерам виконати повторну пересилку до настання тайм-ауту.

10.13.1 Повільний старт

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

Нове з'єднання, миттєво запускає пересилку великого обсягу даних в уже і так навантаженої мережі, може привести до проблем. Ідея повільного старту полягає в забезпеченні новому з'єднанню успішного запуску з повільним збільшенням швидкості пересилання даних відповідно до реальної навантаженням на мережу. Відправник обмежується розміром навантажувального вікна, а не великим за розміром прийомним вікном.

навантажувальний вікно(Congestion window) починається з розміру в 1 сегмент. Для кожного сегмента з успішно отриманим ACK розмір навантажувального вікна збільшується на 1 сегмент, поки воно залишається менше, ніж приймальне вікно. Якщо мережа не перевантажена, навантажувальний вікно поступово досягне розміру приймального вікна. При нормальному стані пересилання розміри цих вікон будуть збігатися.

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

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

10.13.2 Синдром "нетямущого вікна"

У перших реалізаціях TCP / IP розробники зіткнулися з феноменом синдрому "нетямущого вікна"(Silly Window Syndrome - SWS), який проявлявся досить часто. Для розуміння подій, що відбуваються розглянемо наступний сценарій, що призводить до небажаних наслідків, але цілком можливий:

1. Передавальний додаток швидко відсилає дані.

2. Приймаюча додаток читає з вхідного буфера по 1 байту даних (тобто повільно).

3. Вхідний буфер після читання швидко заповнюється.

4. Приймаюча додаток читає 1 байт, і TCP відправляє ACK, що означає "Я маю вільне місце для 1 байта даних".

5. Передавальний додаток відправляє по мережі пакет TCP з 1 байта.

6. Приймаючий TCP посилає ACK, що означає "Дякую. Я отримав пакет і не маю більше вільного місця".

7. Приймаюча додаток знову читає 1 байт і відправляє ACK, і весь процес повторюється.

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

Реальні ситуації, звичайно, не настільки екстремальні. Швидкий відправник і повільний одержувач обмінюватимуться невеликими (щодо максимального розміру сегмента) шматками даних і перемикатися з майже заповненому приймального вікна. На рис. 10.18 показані умови для появи синдрому "нетямущого вікна".


Мал. 10.18.Буфер приймального вікно з дуже малим розміром вільного простору

Вирішити цю проблему нескладно. Як тільки приймальне вікно скорочується на довжину, меншу ніж даний цільової розмір, TCP починає обманювати відправника. У цій ситуації TCP не повинен вказувати відправнику на додатковепростір у вікні, коли приймаюча прикладна читає дані з буфера невеликими порціями. Замість цього потрібно тримати звільняються ресурси в секреті від відправника до тих пір, поки їх не буде достатня кількість. Рекомендується розмір в один сегмент, крім випадків, коли весь вхідний буфер зберігає єдиний сегмент (в останньому випадку використовується розмір, рівний половині буфера). Цільовий розмір, про який повинен повідомляти TCP, можна висловити як:

minimum (1/2 вхідного буфера, Максимальний розмір сегмента)

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

Запропоноване рішення легко перевірити в розглянутому вище випадку з висновком ACK для кожного з отриманих байтів. Цей же спосіб придатний і для випадку, коли вхідний буфер може зберігати кілька сегментів (як часто буває на практиці). Швидкий відправник заповнить вхідний буфер, але приймач вкаже, що не має вільного місця для розміщення інформації, і не відкриє цей ресурс, поки його розмір не досягне цілого сегмента.

10.13.3 Алгоритм Нейгла

Відправник повинен незалежно від одержувача виключити пересилання дуже коротких сегментів, акумулюючи дані перед відправленням. Алгоритм Нейгла (Nagle) реалізує дуже просту ідею, що дозволяє знизити кількість пересилаються по мережі коротких датаграмм.

Алгоритм рекомендує затримати пересилання даних (і їх виштовхування) на час очікування ACK від раніше переданих даних. Акумулюються дані пересилаються після отримання ACK на раніше відправлену порцію інформації, або після отримання для відправки даних в розмірі повного сегмента або по завершенні тайм-ауту. Цей алгоритм не слід застосовувати для додатків реального часу, які повинні відправляти дані якомога швидше.

10.13.4 Затриманий ACK

Ще одним механізмом підвищення продуктивності є спосіб затримки ACK. Скорочення числа ACK знижує смугу пропускання, яку можна використовувати для пересилання іншого трафіку. Якщо партнер по TCP трохи затримає відправку ACK, то:

■ Можна підтвердити прийом декількох сегментів одним ACK.

■ приймає додаток здатне отримати певний обсяг даних в межах інтервалу тайм-ауту, тобто в ACK може потрапити вихідний заголовок, і не буде потрібно формування окремого повідомлення.

З метою виключення затримок при пересиланні потоку повнорозмірних сегментів (наприклад, при обміні файлами), ACK повинен надсилатися, по крайней мере, для кожного другого повного сегмента.

Багато реалізації використовують тайм-аут в 200 мс. Але затриманий ACK не знижує швидкість обміну. При надходженні короткого сегмента у вхідному буфері залишається ще досить вільного місця для отримання нових даних, а відправник може продовжити пересилання (крім того, повторна пересилання зазвичай виконується набагато повільніше). Якщо ж надходить цілий сегмент, потрібно в ту ж секунду відповісти на нього повідомленням ACK.

10.13.5 Тайм-аут повторної пересилки

Після відправки сегмента TCP встановлює таймер і відстежує надходження ACK. Якщо ACK не отримана протягом періоду тайм-ауту, TCP виконує повторну пересилку сегмента (ретрансляцію). Проте яким повинен бути період тайм-ауту?

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

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

Алгоритми Джекобсон, Керна і Партриджа (описані в статтях , Van Jacobson, і Improving Round-Trip Time Estimates in Reliable Transport Protocols, Karn і Partridge) дозволяють адаптувати TCP до зміни мережевих умов. Ці алгоритми рекомендовані до використання в нових реалізаціях. Ми коротко розглянемо їх нижче.

Здоровий глузд підказує, що найкращою основою оцінки правильного часу тайм-ауту для конкретного з'єднання може бути відстеження часу циклу(Round-trip time) як проміжку між відправкою даних і отриманням підтвердження про їх прийом.

Хороші рішення для наступних величин можна отримати на основі елементарних статистичних відомостей (див. Рис. 10.19), які допоможуть вирахувати час тайм-ауту. Однак не потрібно покладатися на усереднені величини, оскільки більше половини оцінок буде більше, ніж середньостатистична величина. Розглянувши пару відхилень, можна отримати більш правильні оцінки, що враховують нормальний розподіл і знижують занадто довгий час очікування повторної пересилки.


Мал. 10.19.Розподіл значень часу циклу

Немає необхідності в великому обсязі обчислень для отримання формальних математичних оцінок відхилень. Можна використовувати досить грубі оцінки на основі абсолютної величини різниці між останнім значенням і середньостатистичної оцінкою:

Останнє відхилення = | Останній цикл - Середня величина |

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

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

Наприклад, якщо 1000 значень дали середньостатистичну величину в 170 одиниць, але далі були заміряні 50 значень із середнім в 282, то поточний середній буде:

170 × 1000/1050 + 282 × 50/1050 = 175

Більш резонною буде величина згладженого часу циклу(Smoothed Round-Trip Time - SRTT), яка враховує пріоритет більш пізніх значень:

Нове SRTT = (1 - α) × (старе SRTT) + α × Останнє значення циклу

Значення α знаходиться між 0 і 1. збільшення апризводить до більшого впливу поточного часу циклу на згладжені середнє значення. Оскільки комп'ютери швидко можуть виконувати розподіл на ступеня числа 2, зрушуючи двійкові числа направо, для α завжди вибирається значення (1/2) n (зазвичай 1/8), тому:

Нове SRTT = 7/8 × старе SRTT + 1/8 × Останнім часом циклу

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


Таблиця 10.2 Обчислення згладженого часу циклу

старе SRTT Саме останнє RTT (7/8) × (старе SRTT) + (1/8) × (RTT)
230.00 294 238.00
238.00 264 241.25
241.25 340 253.59
253.59 246 252.64
252.64 201 246.19
246.19 340 257.92
257.92 272 259.68
259.68 311 266.10
266.10 282 268.09
268.09 246 265.33
265.33 304 270.16
270.16 308 274.89
274.89 230 269.28
269.28 328 276.62
276.62 266 275.29
275.29 257 273.00
273.00 305 277.00

Тепер виникає питання про вибір значення для тайм-ауту повторної пересилки. Аналіз величин часу циклу показує суттєве відхилення цих значень від поточної середньої величини. Має сенс встановити кордон для величини відхилень (девіацій). Хороші величини для тайм-ауту повторної пересилки (в стандартах RFC цю величину називають Retransmission TimeOut - RTO) дає наступна формула з обмеженням згладженого відхилення (SDEV):

Т = Тайм-аут повторної пересилки = SRTT + 2 × SDEV

Т = SRTT + 4 × SDEV

Для обчислення SDEV спочатку визначають абсолютне значення поточного відхилення:

DEV = | Останнім часом циклу - старе SRTT |

Потім використовують формулу згладжування, щоб врахувати останнє значення:

Нове SDEV = 3/4 × старе SDEV + 1/4 × DEV

Залишається одне питання - які взяти початкові значення? рекомендується:

Початковий тайм-аут = 3 з

Початковий SRTT = 0

Початковий SDEV = 1,5 с

Ван Джекобсон визначив швидкий алгоритм, який дуже ефективно обчислює тайм-аут повторної пересилки даних.

10.13.6 Приклад статистики

Наскільки успішно буде працювати обчислений вище тайм-аут? При реалізації отриманого значення спостерігалися значні підвищення продуктивності. Прикладом можуть служити статистичні дані команди netstat, Отримані на системі tigger- сервері Інтернету, до якого звертається безліч хостів з усього світу.


1510769 packets (314955304 bytes) received in-sequence

системою tiggerбули повторно передані менш ніж 2,5% сегментів даних TCP. Для півтора мільйона входять сегментів даних (інші є чистими повідомленнями ACK) дубльовані були тільки 0,6%. При цьому слід враховувати, що рівень втрат у вхідних даних приблизно відповідає рівню для вихідних сегментів. Таким чином, даремний трафік повторної пересилки складає близько 0,6% від загального трафіку.

10.13.7 Обчислення після повторної відправки

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

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

10.13.8 Дії після повторної пересилки

Але що відбувається до отримання підтвердження? Після повторної пересилки поведінку TCP радикально змінюється в основному через втрату даних від перевантаження в мережі. Отже, реакцією на повторну відправку даних буде:

■ Зниження швидкості повторної пересилки

■ Боротьба з перевантаженням мережі за допомогою скорочення загального трафіку

10.13.9 Експоненціальне гальмування

Після повторної пересилки подвоюється інтервал тайм-ауту. Однак що станеться при повторному переповненні таймера? Дані будуть відправлені ще раз, а період повторної пересилки знову подвоїться. Цей процес називається експоненціальним гальмуванням(Exponential backoff).

Якщо продовжує проявлятися несправність мережі, період тайм-ауту буде подвоюватися до досягнення встановленого максимального значення (зазвичай - 1 хв). Після тайм-ауту може бути відправлений тільки один сегмент. Тайм-аут настає і при перевищенні заздалегідь встановленого значення для кількості пересилань даних без отримання ACK.

10.13.10 Зниження перевантажень за рахунок зменшення пересилаються по мережі даних

Скорочення обсягу даних, що пересилаються дещо складніше, ніж розглянуті вище механізми. Воно починає працювати, як і вже згаданий повільний старт. Але, оскільки встановлюється межа для рівня трафіку, який може в початковий момент привести до проблем, буде реально сповільнюватися швидкість обміну внаслідок збільшення розміру навантажувального вікна по одному сегменту. Потрібно встановити значення кордону для реального скорочення швидкості відправки. Спочатку обчислюється межа небезпеки (danger threshold):

Кордон - 1/2 minimum (поточний навантажувальний вікно, приймальне вікно партнера)

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

■ Встановити розмір навантажувального вікна в один сегмент.

■ Для кожного отриманого ACK збільшувати розмір навантажувального вікна на один сегмент, поки не буде досягнута межа (що дуже нагадує механізм повільного старту).

■ Після цього з кожним отриманим ACK до навантажувальних вікна додавати менше значення, яке вибирається на основі швидкості збільшення по одному сегменту для часу циклу (збільшення обчислюється як MSS / N, де N - розмір навантажувального вікна в сегментах).

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

■ Відправляється 1 сегмент (навантажувальний вікно = 1 сегмент).

■ Отримано ACK - відправляється 2 сегмента.

■ Отримано ACK для 2 сегментів - надсилається 4 сегмента, (досягається межа).

■ Отримано ACK для 4 сегментів. Надсилається 5 сегментів.

■ Отримано ACK для 5 сегментів. Надсилається 6 сегментів.

■ Отримано ACK для 6 сегментів. Надсилається 7 сегментів.

■ Отримано ACK для 7 сегментів. Надсилається 8 сегментів (навантажувальний вікно за розміром знову стало одно приймального вікна).

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


Мал. 10.20.Обмеження швидкості пересилання під час перевантаження

10.13.11 Дубльовані ACK

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

Беручи сегмент, що надійшов не по порядку, одержувач відсилає назад ACK, який вказує на перший байт втраченихданих (див. рис. 10.21).


Мал. 10.21.дубльовані ACK

Відправник не виконує миттєвої повторної пересилки даних, оскільки IP може і в нормальному режимі доставляти дані одержувачу без послідовності відправки. Але коли отримано кілька додаткових ACK на дублювання даних (наприклад, три), то відсутній сегмент буде відправлений, не чекаючи завершення тайм-ауту.

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

Відповідно до стандарту Host Requirements(Вимоги до хостів) TCP повинен виконувати той же самий повільний старт, як це описано вище, при придушенні джерела (source quench). Однак повідомлення про це не є цілеспрямованим або ефективним, оскільки отримало це повідомлення з'єднання може і не створювати занадто великого трафіку. Поточна специфікація Router Requirements(Вимоги до маршрутизаторів) вказує, що маршрутизатори не повинніпосилати повідомлень про придушення джерела.

10.13.13 Статистика TCP

Нарешті, давайте розглянемо статистичні повідомлення команди netstat,щоб побачити в роботі багато з описаних вище механізмів.

Пакетами іменуються сегменти.
879137 data packets (226966295 bytes)
21815 data packets (8100927 bytes) retransmitted
Повторна пересилання.
132957 ack-only packets (104216 delayed)
Відзначимо велику кількість

затриманих ACK.

Зондування відкриття вікна

нульового розміру.

Це повідомлення SYN і FIN.
762469 acks (for 226904227 bytes)
Сигнал про пакетах, які прибули

поза послідовності.

1510769 packets (314955304 bytes)
9006 completely duplicate packets (867042 bytes)
Результат тайм-ауту при реальній

доставці даних.

74 packets with some dup. data (12193 bytes duped)
З метою більшої ефективності

деякі дані при повторній відправці були перепакетіровани для включення додаткових байт.

13452 out-of-order packets (2515087 bytes)
530 packets (8551 bytes) of data after window
Можливо, ці дані були

включені в повідомлення зондування.

402 packets received after close
Це наступні повторні

відправки.

108 discarded for bad checksums
Невірна контрольна сума TCP.
0 discarded for bad header offset fields
7 discarded because packet too short
14677 connections established (including accepts)
18929 connections closed (including 643 drops)
4100 embryonic connections dropped
572187 segments updated rtt (of 587397 attempts)
Невдалі спроби зміни

часу циклу, оскільки ACK не встиг прийти до завершення тайм-ауту,

26 connections dropped by rexmit timeout
Наступні невдалі спроби

повторної відправки, що вказує на втрачене з'єднання.

Тайм-аути по зондування

нульового вікна.

Тайм-аути по перевірці

непрацюючого з'єднання.

472 connections dropped by keepalive

10.14 Відповідність вимогам розробника

Поточний стандарт TCP вимагає, щоб реалізації твердо дотримувалися процедури повільного старту при ініціалізації з'єднання і використовували алгоритми Керна і Джекобсон для оцінки тайм-ауту повторної відправки даних і управління навантаженням. Тести показали, що ці механізми призводять до значного підвищення продуктивності.

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

10.15 Бар'єри для продуктивності

TCP довів свою гнучкість, працюючи в мережах зі швидкістю обміну в сотні або мільйони біт за секунду. Цей протокол дозволив досягти хороших результатів у сучасних локальних мережах з топологиями Ethernet, Token-Ring і Fiber Distributed Data Interface (FDDI), а також для низькошвидкісних ліній зв'язку або сполук на далекі відстані (подібних супутниковим зв'язків).

TCP розроблений так, щоб реагувати на екстремальні умови, наприклад на перевантаження в мережі. Однак в поточній версії протоколу є особливості, що обмежують продуктивність в перспективних технологіях, які пропонують смугу пропускання в сотні і тисячі мегабайт. Щоб зрозуміти проблеми, що виникають, розглянемо простий (хоча і нереалістичний) приклад.

Припустимо, що при переміщенні файлу між двома системами необхідно виконувати обмін безперервним потоком настільки ефективно, наскільки це можливо. Припустимо, що:

■ Максимальний розмір сегмента приймача - 1 Кбайт.

■ Приймальне вікно - 4 Кбайт.

Смуга пропускання дозволяє пересилати по два сегменти за 1 с.

■ приймає додаток поглинає дані по мірі їх надходження.

■ Повідомлення ACK прибувають через 2 с.

Відправник здатний посилати дані безперервно. Адже коли виділений для вікна обсяг буде заповнений, прибуває ACK, що дозволяє відправку іншого сегмента:

Через 2 з:

RECEIVE ACK OF SEGMENT 1, CAN SEND SEGMENT 5.
RECEIVE ACK OF SEGMENT 2, CAN SEND SEGMENT 6.
RECEIVE ACK OF SEGMENT 3, CAN SEND SEGMENT 7.
RECEIVE ACK OF SEGMENT 4, CAN SEND SEGMENT 8.

Ще через 2 з:

RECEIVE ACK OF SEGMENT 5, CAN SEND SEGMENT 9.

Якщо приймальне вікно було тільки в 2 Кбайт, відправник буде змушений чекати одну секунду з кожних двох перед відправкою наступних даних. Фактично, щоб утримати безперервний потік даних, приймальне вікно повинно мати розмір не менше:

Вікно = Смуга пропускання × Час циклу

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

Тепер розглянемо, що відбувається з високошвидкісними сполуками. Наприклад, якщо смуга пропускання і швидкість пересилання вимірюються 10 млн. Біт в секунду, але час циклу становить 100 мс (1/10 секунди), то для безперервного потоку приймальне вікно повинно зберігати, принаймні, 1 000 000 біт, тобто . 125 000 байт. Але найбільше число, яке можна записати в поле заголовка для приємного вікна TCP, так само 65 536.

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

Зараз активно проводяться нові дослідження для поліпшення TCP / IP і усунення згаданих вище перешкод.

10.16 Функції TCP

Дана глава присвячена численним функціям TCP. Нижче перераховані основні з них:

■ Зв'язування портів з сполуками

■ Ініціалізація з'єднань за допомогою трехшаговий підтвердження

■ Виконання повільного старту, що виключає перевантаження мережі

■ Сегментація даних при пересиланні

■ Нумерація даних

■ Здійснення надходять дубльованих сегментів

■ Обчислення контрольних сум

■ Регулювання потоку даних через приймальне вікно і вікно відправки

■ Завершення з'єднання встановленим способом

■ Переривання з'єднання

■ Пересилання термінових даних

■ Позитивне підтвердження повторної пересилки

■ Обчислення тайм-ауту повторної пересилки

■ Зниження зворотного трафіку при перевантаженні мережі

■ Сигналізація надходження сегментів не по порядку

■ Зондування закриття приймального вікна

10.17 Стану TCP

З'єднання TCP проходить кілька стадій: встановлюється з'єднання за допомогою обміну повідомленнями, потім пересилаються дані, а далі з'єднання закривається за допомогою обміну спеціальними повідомленнями. Кожен крок у роботі з'єднання відповідає певному станомцього з'єднання. Програмне забезпечення TCP на кожному кінці з'єднання постійно відстежує поточний стан іншого боку з'єднання.

Нижче ми коротко розглянемо типову зміну станів сервера і клієнта, розташованих на різних кінцях з'єднання. Ми не ставимо за мету дати вичерпний опис всіх можливих станів при пересиланні даних. Воно наведено в RFC 793 і документі Host Requirements.

Під час установки з'єднань сервер і клієнт проходять схожі послідовності станів. Стану сервера показані в таблиці 10.3, а стану клієнта - в таблиці 10.4.


Таблиця 10.3 Послідовність станів сервера

стан сервера подія опис
CLOSED (закрито) Фіктивне стан перед початком установки з'єднання.
Пасивне відкриття серверним додатком.
LISTEN (відстеження) Сервер очікує з'єднання з клієнтом.
Сервер TCP отримує SYN і посилає SYN / ACK. Сервер отримав SYN і послав SYN / ACK. Переходить до очікування ACK.
SYN-RECEIVED Сервер TCP отримує ACK.
ESTABLISHED (встановлено) Отримано ACK, відкрито з'єднання.

Таблиця 10.4 Послідовність станів клієнта

Якби партнери одночасно намагалися встановити з'єднання один з одним (що трапляється вкрай рідко), кожен пройшов би через стану CLOSED, SYN-SENT, SYN-RECEIVED і ESTABLISHED.

Кінцеві боку з'єднання залишаються в стані ESTABLISHED, поки одна зі сторін не приступить до закриттяз'єднання, пославши сегмент FIN. В процесі звичайного закриття сторона, яка ініціює це закриття, проходить через стану, показані в таблиці 10.5. Її партнер проходить через стану, представлені в таблиці 10.6.


Таблиця 10.5 Послідовність станів боку, закриває з'єднання

Стану закриває боку подія опис
ESTABLISHED Локальне додаток запитує закриття з'єднання.
TCP посилає FIN / ACK.
FIN-WAIT-1 Закриває сторона очікує відповіді партнера. Нагадаємо, що від партнера все ще можуть прибувати нові дані.
TCP отримує ACK.
FIN-WAIT-2 Закриває сторона отримала ACK від партнера, але ще не прийшов FIN. Закриває сторона очікує FIN, приймаючи дані, що надходять.
TCP отримує FIN / ACK.
Посилає ACK.
TIME-WAIT З'єднання підтримується в невизначеному стані, щоб дозволити прибути або відкинути все ще існуючі в мережі дубльовані дані або дубльований FIN. Період очікування вдвічі більше оцінки максимальної тривалості життя сегмента.
CLOSED

Таблиця 10.6 Послідовність станів партнера по закриттю з'єднання

стан партнера подія опис
ESTABLISHED TCP отримує FIN / ACK.
CLOSE-WAIT Прибув FIN.
TCP посилає ACK.
TCP очікує від свого застосування закриття з'єднання. У цей момент додаток може посилати досить велика кількість даних.
Локальна програма ініціалізує закриття з'єднання.
TCP посилає FIN / ACK.
LAST-ACK TCP очікує кінцевий ACK.
TCP отримує ACK.
CLOSED Вилучена вся інформація про з'єднання.

10.17.1 Аналіз станів з'єднання TCP

команда netstat -anдозволяє перевірити поточний стан з'єднання. Нижче показані з'єднання в станах listen, startup, established, closingі time-wait.

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

Pro Recv-Q Send-Q Local Address Foreign Address (state)
Tcp 0 0 128.121.50.145.25 128.252.223.5.1526 SYN_RCVD
Tcp 0 0 128.121.50.145.25 148.79.160.65.3368 ESTABLISHED
Tcp 0 0 127.0.0.1.1339 127.0.0.1.111 TIME_WAIT
Tcp 0 438 128.121.50.145.23 130.132.57.246.2219 ESTABLISHED
Tcp 0 0 128.121.50.145.25 192.5.5.1.4022 TIME_WAIT
Tcp 0 0 128.121.50.145.25 141.218.1.100.3968 TIME_WAIT
Tcp 0 848 128.121.50.145.23 192.67.236.10.1050 ESTABLISHED
Tcp 0 0 128.121.50.145.1082 128.121.50.141.6000 ESTABLISHED
Tcp 0 0 128.121.50.145.1022 128.121.50.141.1017 ESTABLISHED
Tcp 0 0 128.121.50.145.514 128.121.50.141.1020 CLOSE_WAIT
Tcp 0 1152 128.121.50.145.119 192.67.239.23.3572 ESTABLISHED
Tcp 0 0 128.121.50.145.1070 192.41.171.5.119 TIME_WAIT
Tcp 579 4096 128.121.50.145.119 204.143.19.30.1884 ESTABLISHED
Tcp 0 0 128.121.50.145.119 192.67.243.13.3704 ESTABLISHED
Tcp 0 53 128.121.50.145.119 192.67.236.218.2018 FIN_WAIT_1
Tcp 0 0 128.121.50.145.119 192.67.239.14.1545 ESTABLISHED

10.18 Зауваження про реалізаціях

З самого початку протокол TCP призначений для взаємодії мережевого обладнання від різних виробників. Специфікація TCP не вказує точно, як повинні працювати внутрішні структури реалізації. Ці питання залишені для розробників, які покликані знайти найкращі механізми для кожної конкретної реалізації.

Навіть RFC 1 122 (документ Host Requirements -вимоги до хостів) залишає достатню свободу для варіацій. Кожна з функцій, що реалізовуються маркується певним рівнем сумісності:

■ MAY (Дозволено)

■ MUST NOT (Не потрібно)

На жаль, іноді зустрічаються продукти, які не реалізують вимоги MUST. В результаті користувачі відчувають незручності від зниження продуктивності.

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

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

Фактично розробники засновують свої комплекти інструментів на програмному інтерфейсі Socket, запозичений із Berkeley. Значення програмного інтерфейсу зросла з появою WINSock (Windows Socket), що призвело до швидкого збільшення нових додатків для настільних систем, які могли працювати поверх будь-якого інтерфейсу WINSock, сумісного зі стеком TCP / IP.

10.19 Додаткова література

Оригінал стандарту TCP визначений в RFC 793. Модернізації, виправлення, і вимоги сумісності розглянуті в RFC 1122. Керн (Каш) і Партрідж (Partridge) опублікували статтю Improving Round-Trip Estimates in Reliable Transport Protocolsв журналі Proceedings of the ACM SIGCOMM 1987.Стаття Джекобсон (Jacobson) Congestion Avoidance and Controlз'явилася в Proceedings of the ACM SIGCOMM 1988 Workshop.Джекобсон видав також кілька RFC, котрі переглядають алгоритми підвищення продуктивності.

Сподобалася стаття? Поділіться з друзями!