Мережева взаємодія

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

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

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

Модель OSІ

На початку 80-х років ряд міжнародних організацій зі стандартизації, зокрема Міжнародна організація з стандартизації (ISO) розробили стандартну модель взаємодії відкритих систем (Open System Interconnection , OSI).

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

В моделі OSI засоби взаємодії поділяються на сім рівнів: прикладний, представлення, сеансовий, транспортний, мережевий, канальний і фізичний. Кожний рівень пов`язаний з цілком певним аспектом взаємодії мережевих пристроїв.



Додатки можуть реалізовувати власні протоколи взаємодії, використовуючи для цих цілей багаторівневу сукупність системних засобів. Саме для цього в розпорядження програмістів надається прикладний програмний інтерфейс (Application Program Interface, API). Відповідно до ідеальної схемою моделі OSI додаток може звертатися із запитами тільки до найвищого рівня - прикладного, однак на практиці багато стеків комунікаційних протоколів надають можливість програмістам безпосередньо звертатися до сервісів, або служб, нижчих рівнів.

Розглянемо приклад роботи даної моделі на прикладі. Отже, нехай додаток вузла 1 хоче взаємодіяти з додатком вузла 2. Для цього додаток А звертається із запитом до прикладного рівня (7 рівень моделі  OSI). На підставі цього запиту програмне забезпечення прикладного рівня формує повідомлення стандартного формату. Після формування повідомлення прикладний рівень направляє його вниз по стеку до рівня представлення. Протокол рівня представлення на підставі інформації, отриманої із заголовка повідомлення прикладного рівня, виконує необхідні дії і додає до повідомлення власну службову інформацію - заголовок рівня представлення, в якому містяться вказівки для протоколу рівня подання машини-адресата. Отримане в результаті повідомлення передається вниз сеансовому рівню, який, в свою чергу, додає свій заголовок, і т. д. Нарешті, повідомлення досягає нижнього, фізичного, рівня, який, власне, і передає його по лініях зв'язку машині-адресату. До цього моменту повідомлення «обростає» заголовками всіх рівнів. Фізичний рівень поміщає повідомлення на фізичний вихідний інтерфейс комп'ютера 1, і воно починає свою «подорож» по мережі (до цього моменту повідомлення передавалося від одного рівня до іншого в межах комп'ютера 1). 
Коли повідомлення по мережі поступає на вхідний інтерфейс комп'ютера 2, воно приймається її фізичним рівнем і послідовно переміщається вгору з рівня на рівень. Кожен рівень аналізує і обробляє заголовок свого рівня, виконуючи відповідні функції, а потім видаляє цей заголовок і передає повідомлення верхньому рівню. Як видно з опису, протокольні суті одного рівня не спілкуються між собою безпосередньо, в цьому спілкуванні завжди беруть участь посередники - кошти протоколів нижчих рівнів. І тільки фізичні рівні різних вузлів взаємодіють безпосередньо.

Наочний приклад передачі даних між двома вузлами
Коротко розглянемо кожний з рівнів моделі OSI.

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

Фізичний рівень передає потоки бітів по каналу зв`язку


Канальний рівень забезпечує прозорість з'єднання для мережевого рівня. 

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

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

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

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

Принцип дії канального рівня
Мережевий рівень служить для утворення єдиної транспортної системи, що об'єднує декілька мереж інтернетом.

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


Комутатор працює на нижчих двох рівнях моделі OSI, маршрутизатор працює на нижчих трьогх рівнях  

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

Транспортний рівень забезпечує додаткам і верхнім рівніям стека - прикладному, представлення і сеансовому - передачу даних з тим ступенем надійності, яка їм потрібна.

Модель OSI визначає п'ять класів транспортного сервісу: від нижчого класу 0 до вищого класу 4. Ці види сервісу відрізняються якістю наданих послуг: терміновістю, можливістю відновлення перерваного зв'язку, наявністю засобів мультиплексування декількох з'єднань між різними прикладними протоколами через загальний транспортний протокол, а головне - здатністю до виявлення і виправлення помилок передачі, таких як спотворення, втрата і дублювання пакетів.

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

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




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


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

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

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

Важливо розумітити, що модель OSI є концептуальною СХЕМОЮ взаємодії відкритих систем і не містить специфікацій конкретних протоколів.

Стек протоколів OSI

Розглянемо стек протоколів OSI, який ,на відміну від моделі OSI, містить набір конкретних специфікацій протоколів. На відміну від інших стеків протоколів стек OSI повністю відповідає моделі OSI, включаючи специфікації протоколів для всіх семи рівнів взаємодії, визначених у цій моделі. 
Протоколи стека OSI відрізняються складністю і неоднозначністю специфікацій. Ці властивості стали результатом спільної політики розробників стека, які прагнули врахувати в своїх протоколах все різноманіття вже існуючих і нових технологій.
На фізичному і канальному рівнях стек OSI підтримує протоколи Ethernet, Token Ring, FDDI, а також протоколи LLC, X.25 і ISDN, тобто, як і більшість інших стеків, використовує всі розроблені поза стека популярні протоколи нижніх рівнів.
Мережевий рівень включає порівняно рідко використовувані протоколи Connection- oriented Network Protocol (CONP) і Connectionless Network Protocol (CLNP). Як випливає з назв, перший з них орієнтований на з'єднання (connection-oriented), другий - на його відсутність (connectionless).


Протоколи стеку OSI

Більш популярними протоколами маршрутизації стека OSI є: протокол між кінцевою і проміжною системами (End System - Intermediate System, ES-IS) і між проміжними системами (Intermediate System - Intermediate System, IS-IS).
Транспортний рівень стека OSI відповідно до функцій, визначених для нього в моделі OSI, приховує відмінності між мережевими сервісами з встановленням з'єднання і без встановлення з'єднання, так що користувачі отримують необхідну якість обслуговування незалежно від нижчого мережного рівня. Щоб забезпечити це, транспортний рівень вимагає, щоб користувач задав потрібну якість обслуговування.

Служби прикладного рівня забезпечують передачу файлів, емуляцію термінала, сервіс каталогів і пошту. З них найбільш популярними є сервіс каталогів (стандарт Х.500), електронна пошта (Х.400), протокол віртуального терміналу (VTP), протокол передачі, доступу та управління файлами (FTAM), протокол пересилки і управління роботами (JTM).

Стек протоколів TCP/IP
А тепер перейдемо до розгляду стеку протоколів TCP/IPСьогодні цей стек використовується для зв’язку вузлів всесвітньої інформаційної мережі Інтернет.


Стек протоколів TCP/IP порівняно з моделлю OSI

Стек TCP/IP на нижньому рівні підтримує всі популярні стандарти фізичного й канального рівнів: для локальних мереж — це Ethernet, Token Ring, FDDI, для глобальних — протоколи роботи на аналогових комутованих і виділених лініях SLIP, PPP, протоколи територіальних мереж X.25 і ISDN. Основними протоколами стека, що дали йому назву, є протоколи IP і TCP. Ці протоколи в термінології моделі OSI належать до мережного і транспортного рівнів, відповідно. IP забезпечує просування пакета по складеній мережі, а TCP гарантує надійність його доставки.
TCP/IP увібрав у себе велику кількість протоколів прикладного рівня. До них належать такі популярні протоколи: FTP, telnet, SMTP, гіпертекстові сервіси служби WWW і багато інших. Дуже корисною властивістю, завдяки якій цей протокол може застосовуватися у великих мережах, є його здатність фрагментувати пакети.
У протоколі TCP/IP інформація передається у вигляді послідовності дейтаграм. Одне повідомлення може передаватися як ряд дейтаграм, які збираються в повідомлення в місці прийому.
На прикладному рівні реалізовані широко використовувані сервіси прикладного рівня. До них належать: протокол передачі файлів між віддаленими системами (FTP), протокол емуляції віддаленого терміналу (telnet), поштові протоколи, протокол вирішення імен (DNS) тощо. Кожна прикладна програма вибирає тип транспортування — або безперервний потік повідомлень, або послідовність окремих повідомлень. Прикладна програма передає дані транспортному рівню в необхідній формі.

Основним завданням транспортного рівня стека TCP/IP є взаємодія між прикладними програмами. Транспортний рівень виконує дві функції:
  •  управляє потоком, що забезпечується механізмом ковзних вікон;
  •  гарантує надійність передачі завдяки наявності порядкових номерів сегментів і підтверджень.
Для цього в TCP/IP використаний механізм підтвердження правильного прийому з дублюванням передачі загублених пакетів або пакетів, що надійшли з помилками. Транспортний рівень приймає дані від декількох прикладних програм і надсилає їх нижньому рівню. При цьому він долучає додаткову інформацію до кожного пакета, у тому числі контрольну суму.
На транспортному рівні використовуються два протоколи:
  • TCP — протокол із квитуванням і встановленням з’єднання. Він відповідає за розбиття повідомлень на сегменти, їх збирання у вузлі призначення, повторне відсилання всього, що виявилося не отриманим, і збирання повідомлень із сегментів. Протокол TCP забезпечує гарантовану доставку даних за рахунок утворення логічних (віртуальних) з’єднань між віддаленими прикладними процесами;
  • протокол дейтаграм користувача (User Datagram Protocol, UDP), не орієнтований на встановлення з’єднання. Хоча протокол UDP і відповідає за передачу повідомлень, на цьому рівні квитування не застосовується, оскільки відсутнє програмне забезпечення для перевірки доставки сегментів.


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

Як основний протокол мережного рівня в стеку протоколів ТСР/IP використовується протокол IP, що створювався саме з метою передачі інформації в розподілених мережах.



Рівень мережного інтерфейсу (рівень доступу) стека TCP/IP. Найнижчий рівень стека TCP/IP відповідає фізичному і канальному рівням моделі OSI. У стеку протоколів TCP/IP цей рівень не регламентований. Рівень мережного інтерфейсу відповідає за прийом дейтаграмм і передачу їх конкретною мережею. Інтерфейс із мережею може бути реалізований драйвером пристрою або системою (комутатор, маршрутизатор), що використовує свій протокол канального рівня. Він підтримує стандарти фізичного і канального рівнів популярних локальних мереж: Ethernet, Token Ring, FDDI тощо. Для територіально-розподілених мереж підтримуються протоколи з’єднань РРР і SLIP, а для глобальних мереж — протокол Х.25. 

Сокети

Більшість додатків складаються з процесів, які взаємодіють між собою, і відправляють один одному повідомлення. Процеси відправляють і приймають повідомлення через програмний інтерфейс, званий сокетом
Як ми бачимо з малюнка, сокет - це інтерфейс між прикладним і транспортним рівнями всередині хоста. Його визначають також як інтерфейс програмування додатків (Application Programming Interface, API) між додатком і мережею, так як сокет - це програмний інтерфейс, за допомогою якого будуються мережеві додатки. Розробник програми керує всім, що знаходиться з боку прикладного рівня сокета, але з боку транспортного рівня він здатний тільки контролювати, по-перше, вибір транспортного протоколу і, по-друге, можливість фіксувати деякі параметри транспортного рівня, такі як максимальний буфер і максимальний розмір сегмента.

Приклад взаємодії між двома процесами за допомогою сокетів

Коли запущений на одному хості процес намагається відправити пакети процесу, який працює на іншому хості, то необхідно знати адресу другого процесу. Для ідентифікації процесу-одержувача необхідна інформація про дві речі: адреса хоста призначення і ідентифікатор, який визначає потрібний нам процес на хості призначення. В якості такого ідентифікатора виступає номер порту призначення. Найбільш популярним мережевим додаткам призначені певні номери портів. Наприклад, веб-сервер ідентифікується портом 80. Процес поштового сервера, який використовує протокол ВМТР, використовує порт 25.
Відображення того, що сокет - це адреса хосту та номер порту призначення 
Номери портів пакетів починаються з 0, а максимальним номером може слугувати 65535. При цьому номера до 1023 включно є унікальними на просторах Інтернету та закріпляються за додатками.
Для тих додатків, які ще не стали настільки поширеними, номери портів призначаються локально розробниками цих програм або операційною системою у відповідь на надходження запиту від програми. На кожному комп'ютері операційна система веде список зайнятих і вільних номерів портів. Під час отримання запиту від програми, що виконується на даному комп'ютері, операційна система виділяє йому перший вільний номер. Такі номери називають динамічними. Надалі всі мережеві додатки повинні адресуватися до даного додатку із зазначенням призначеного йому динамічного номера порту.

API

API - це Application Program Interface або програмний інтерфейс програми. Це певний набір протоколів, підпрограм і інструментів для створення програмних додатків. API це те, що дозволяє налаштувати як різні компоненти програми повинні ефективно взаємодіяти. API, який працює за призначенням, повинен спрощувати роботу програмістів і полегшувати розробку певного продукту. 
API є ланкою між програмістом та додатком

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

Основні протоколи: 

Протокол IP (Internet protocol) - основний протокол мережного рівня. Визначає спосіб адресації на мережевому рівні. Забезпечує маршрутизацію в мережах, що представляють собою об'єднання мереж, що базуються на різних мережевих технологіях.
Протокол ARP (Address Resolution Protocol) - допоміжний протокол стека TCP / IP, призначений для визначення апаратної адреси вузла призначення по заданому IP-адресу.
Протокол ICMP (Internet Control Message Protocol) - допоміжний протокол стека TCP / IP, призначений для обміну інформацією про помилки передачі даних протоколом IP, а також для обміну інформацією, що управляє на мережевому рівні. Зокрема, утиліта PING використовує цей протокол для посилки так званого "луна-запиту".
Протокол НТТР - використовується для організації доступу до загальних даних, розташованих на веб-серверах, з метою публікації і читання загальнодоступної інформації. Протокол HTTP описує взаємодію між HTTP-серверами (веб-серверами) і HTTP-клієнтами (веб-браузерами).
Протокол FTP - служба Інтернету, що забезпечує передачу файлів між комп'ютерами. 
Протокол SMTP - застосовується поштовими серверами для передачі електронної пошти. Сервер IIS підтримує роботу з протоколом SMTP для обробки поштових повідомлень;
Протокол Telnet - протокол емуляції терміналу, застосовуваний для підключення до віддалених вузлів мережі. Telnet дозволяє клієнтам віддалено запускати додатки; крім того, він спрощує віддалене адміністрування.
Протокол SNMP - дозволяє централізовано керувати вузлами мережі, наприклад серверами, робочими станціями, маршрутизаторами, мостами і концентраторами. Крім того, SNMP можна використовувати для конфігурування віддалених пристроїв, моніторингу продуктивності мережі, виявлення помилок мережі та спроб несанкціонованого доступу, а також для аудиту використання мережі.

Практична реалізація

Завдяки ресурсам бібліотек С++ можна створити простий ТСР клієнт-серверний додаток.
Загальною блок-схемою роботи ТСР клієнт-серверного додатку є: 

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



Код сервера:

#include <vcl.h>
#pragma hdrstop
#include <iostream>
#include <stdio.h>
#include <winsock2.h>
#include <windows.h>

#define MY_PORT 666
#define PRINTNUSERS if (nclients) printf("%d user on-line\n", nclients); \
else printf("No User on line\n");
DWORD WINAPI SexToClient(LPVOID client_socket);

int nclients = 0;
#pragma argsused
int main(int argc, char* argv[])
{
    char buff[1024];
    printf("TCP SERVER DEMO\n");
    if (WSAStartup(0x0202, (WSADATA *)&buff[0]))
    {
        printf("Error WSAStartup %d\n", WSAGetLastError());
        return -1;
    }
    SOCKET mysocket;
    if ((mysocket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("Error socket %d\n", WSAGetLastError());
        WSACleanup();
        return -1;
    }
    sockaddr_in local_addr;
    local_addr.sin_family = AF_INET;
    local_addr.sin_port = htons(MY_PORT);        
    local_addr.sin_addr.s_addr = 0;
    if (bind(mysocket, (sockaddr *)&local_addr, sizeof(local_addr)))
    {
        printf("Error bind %d\n", WSAGetLastError());
        closesocket(mysocket);
        WSACleanup();
        return -1;
    }
    if (listen(mysocket, 0x100))
    {
        printf("Error listen %d\n", WSAGetLastError());
        closesocket(mysocket);
        WSACleanup();
        return -1;
    }
    printf("Waiting for connections...\n");
    SOCKET client_socket;
    sockaddr_in client_addr;
    int client_addr_size = sizeof(client_addr);
     while ((client_socket = accept(mysocket, (sockaddr *)&client_addr, \ &client_addr_size)))
    {
        nclients++;
        HOSTENT *hst;
        hst = gethostbyaddr((char *)&client_addr. sin_addr.s_addr, 4, AF_INET);

        printf("+%s [%s] new connect!\n",
        (hst) ? hst->h_name : "", inet_ntoa(client_addr.sin_addr));
        PRINTNUSERS
        DWORD thID;
        CreateThread(NULL, NULL, SexToClient, &client_socket, NULL, &thID);
    }
    return 0;
}

DWORD WINAPI SexToClient(LPVOID client_socket)
{
    SOCKET my_sock;
    my_sock = ((SOCKET *)client_socket)[0];
    char buff[20 * 1024];
    #define sHELLO "SOCKET CONNECTED\r\n"
    send(my_sock, sHELLO, sizeof(sHELLO), 0);
    int bytes_recv;
    while ((bytes_recv = recv(my_sock, &buff[0], sizeof(buff), 0)) &&
    bytes_recv != SOCKET_ERROR)
        send(my_sock, &buff[0], bytes_recv, 0);
    nclients--;
    printf("-disconnect\n"); PRINTNUSERS
    closesocket(my_sock);
    return 0;
}

Код клієнта:  

#include <vcl.h>
#pragma hdrstop
#include <stdio.h>
#include <string.h>
#include <winsock2.h>
#include <windows.h>

#define PORT 666
#define SERVERADDR "192.168.1.106"
//!!!В моєму випадку це була ІР-адреса сервера!!!
#pragma argsused
int main(int argc, char* argv[])
{
    char buff[1024];
    printf("TCP DEMO CLIENT\n");
     if (WSAStartup(0x202, (WSADATA *)&buff[0]))
    {
        printf("WSAStart error %d\n", WSAGetLastError());
        return -1;
    }
    SOCKET my_sock;
    my_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (my_sock < 0)
    {
        printf("Socket() error %d\n", WSAGetLastError());
        //system("pause");
        return -1;
    }
    sockaddr_in dest_addr;
    dest_addr.sin_family = AF_INET;
    dest_addr.sin_port = htons(PORT);
    HOSTENT *hst;
     if (inet_addr(SERVERADDR) != INADDR_NONE)
        dest_addr.sin_addr.s_addr = inet_addr(SERVERADDR);
    else
    {
        if (hst = gethostbyname(SERVERADDR))
            ((unsigned long *)&dest_addr.sin_addr)[0] =
            ((unsigned long **)hst->h_addr_list)[0][0];
        else
        {
            printf("Invalid address %s\n", SERVERADDR);
            closesocket(my_sock);
            WSACleanup();
            return -1;
        }
    }
    if (connect(my_sock, (sockaddr *)&dest_addr, sizeof(dest_addr)))
    {
        printf("Connect error %d\n", WSAGetLastError());
        return -1;
    }
    printf("Successfully connected with %s \n \
            Type quit for quit\n\n", SERVERADDR);
     int nsize;
    while ((nsize = recv(my_sock, &buff[0], sizeof(buff) - 1, 0)) != SOCKET_ERROR)
    {
        buff[nsize] = 0;
        printf("S=>C:%s", buff);
        printf("S<=C:"); fgets(&buff[0], sizeof(buff) - 1, stdin);
        if (!strcmp(&buff[0], "quit\n"))
        {
            printf("Exit...");
            closesocket(my_sock);
            WSACleanup();
            return 0;
        }
        send(my_sock, &buff[0], strlen(&buff[0]), 0);
    }
    printf("Recv error %d\n", WSAGetLastError());
    closesocket(my_sock);
    WSACleanup();
    return -1;

}

Додаток в ході виконання:



Роз`єднання зв`язку між сервером та клієнтом

Файли додатку та код знаходяться тут.