Синхронні та асинхронні сокети в windows

  • Синхронні та асинхронні сокети в Windows

    Вступ
    В даному документі ми вивчимо модель Windows Sockets. Ми порівняємо синхронні і асинхронні Window Sockets API і розберемося, чому ж ми повинні використовувати асинхронну модель, і як асинхронне розширення Window Sockets забезпечує кращу працездатність в Windows.

    Synchronous Winsock
    Синхронні Window Sockets API змодельовані на базі стандартних Berkeley Sockets API. Сумісність між цими двома програмними інтерфейсами (API) дуже корисна. Особливо тоді, коли старіші шматки unix-коду повинні бути перенести під Windows.
    Взагалі, синхронні функції Window Sockets API спрямовані на процедурне програмування, використовуючи блокують сокети. Програми читають і пишуть в сокети в блокує манері, цілком покладаючись на операційну систему. Синхронні API працюють краще в command-line орієнтованих багатозадачних системах типу Unix. Це не кращий вибір для Windows.
    Для вирішення проблем блокуючих викликів в орієнтованому на події Windows, Winsock API імітує блокують виклики через використання blocking hook, який містять цикл обробки подій. На жаль, така емуляція блокуючих викликів Window Sockets має деякі обмеження. Зокрема, тільки один блокуючий виклик може бути активним в даний момент. Ці обмеження безпосередньо вдаряють по призначеному для користувача інтерфейсу програми.
    Незважаючи на те, що блокована програма "відпочиває", поки не відбудеться очікуване мережеве подія, оскільки Windows зайнята, це насправді не справжнє блокування. Правильніше буде сказати, що це очікування в циклі, який так само обробляє повідомлення Windows, як наведений нижче приклад:

    Якщо віконне повідомлення, призначене блокує програму, поміщається в чергу повідомлень Windows, воно передається віконної процедури в програмі. Інтерфейс, що належить програмі, залишається активним. Користувач може вибирати елементи меню і натискати клавіші, які потім будуть відправлені програмою. Проблеми можуть виникнути в тому випадку, якщо користувач вибирає такий елемент меню, який викликає іншу мережеву операцію. Тому, що програма вже знаходиться в блокує яких мережевих функцій, не може бути викликана інша функція мережі, і результатом спроби виконати мережеву операцію буде помилка.
    Щоб запобігти цьому подія, програма Windows, яка використовує синхронні блокують API, повинна переконатися, що наступна мережева операція не може бути запущена, поки програма знаходиться в блокує режимі. Програма повинна відключати всі елементи меню і комбінації клавіш, які можуть привести до запуску другий мережевий операції, а це складний процес, особливо якщо шляхів багато, або повністю відключати призначений для користувача інтерфейс від отримання повідомлень від миші і клавіатури і показувати курсор - пісочний годинник.
    Перший варіант більш кращий з точки зору користувача. Користувач не зможе запустити наступну мережеву команду, але, по крайней мере, що залишився в системі буде доступним. Користувач може перейти до іншої виконується програмою і продовжити роботу поки перша програма очікує завершення яких мережевих функцій. Однак, виконати це завдання програмісту аж ніяк не легко.
    У другому випадку користувач опиняється перед курсором - пісочного годинника в очікуванні завершення мережевий операції, коли міг би в цей час виконувати корисну роботу. Багатозадачна середу Windows більш ефективна, ніж однозадачная, оскільки мережа зайнята.
    В обох випадках неможливо виконувати дві мережеві операції в один і той же час в одному додатку. Користувач не може одночасно відправляти лист і перевіряти наявність нових листів на сервері.
    Проблема синхронних Window Sockets API може бути вирішена двома способами. Обидва з використанням неблокірующіх сокетов. Перший метод полягає в тому, що створюються неблокірующіх сокети і функцією select () перевіряють стан цікавить сокета. Потім з гнізд читаються і записуються доступні дані або дані, які можуть бути поміщені в чергу для передачі. Проте, щоб уникнути проблем блокуючих викликів, функція sеlect () повинна бути викликана з параметром timeout рівним нулю, що призводить до неблокірующіх операції. Простіше кажучи, сама функція select () повинна бути викликана так, щоб не замкнути систему, щоб підтримувати свою чергу повідомлень і в той же час дозволити повідомленнями Windows досягати ядра системи. Для цього повинен використовуватися код, що нагадує blocking hook:

    Незважаючи на те, що цей код працює, це жалюгідне рішення. Буде спалюватися вхолосту час CPU, в той час як нічого ефективного виконуватися не буде - в циклі буде виконуватися функція select (). Цей спосіб дуже НЕ економно розпоряджається ресурсами системи і непридатний в подія - орієнтованої операційній системі Windows.
    Більш ефективне рішення всіх проблем блокуючих сокетів - це використання асинхронного розширення Window Sockets API.

    Special thanks: NiFi [UInC], Motrichuk Alexander, Dave Roberts.

    Всі документи і програми на цьому сайті зібрані ТІЛЬКИ для освітніх цілей, ми не відповідаємо ні за які наслідки, які мали місце як наслідок використання цих матеріалів \ програм. Ви використовуєте все вищеперелічене на свій страх і ризик.