Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ППуКМ / Labs 1-7 / Лабораторна робота №4.doc
Скачиваний:
15
Добавлен:
18.03.2016
Размер:
129.02 Кб
Скачать

Лабораторна робота №8 Введення-виведення в Winsock Теоретичні відомості

Ця лабораторна робота присвячена керуванню введенням-виведенням через сокети в WINDOWS-додатках. В Winsock таке керування реалізоване за допомогою режимів роботи та моделей введення-виведення. Режим (mode) сокета визначає поводження функцій, що працюють із сокетом. Модель (model) сокета описує, як додаток виконує введення-виведення при роботі із сокетом. Моделі не залежать від режиму роботи й дозволяють обходити їхні обмеження.

Winsock підтримує два режими: блокуючий (blocking) і неблокуючий (nonblocking). Існує цілий ряд моделей, які допомагають додатку управляти декількома сокетами одночасно в асинхронному режимі: select, WSAAsyncSelect, WSAEventSelect, перекрите введення-виведення (overlapped I/O) і порт завершення (completion port).

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

Блокуючий режим роботи сокета

При блокуванні сокета необхідна обережність, тому що в цьому режимі будь-який виклик функції Winsock саме блокує сокет на якийсь час.

Найпростіший приклад блокування сокета:

SOCKET sock;

char buff[256];

int done = 0;

while(!done)

{

nBytes = recv(sock. buff, 65);

if (nBytes == SOCKET_ERROR)

printf("recv failed with error %d\n",WSAGetLastError());

return;

DoComputationOnData(buff);

}

Проблема в тім, що функція recv може не завершитися ніколи, тому що для цього потрібно зчитати які-небудь дані з буфера системи В такій ситуації деякі програмісти можуть спокуситися «підгляданням» даних (читання без видалення з буфера), використовуючи прапор MSG_PEEK в recv або викликаючи ioctlsocket параметром FIONREAD, але витрати, пов'язані з «підгляданням», великі, тому що необхідно зробити один АБО більше системних викликів для визначення числа доступних байт, після чого однаково доводиться викликати recv для видалення даних з буфера.

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