- •Лабораторна робота №8 Введення-виведення в Winsock Теоретичні відомості
- •Блокуючий режим роботи сокета
- •Неблокуючий режим
- •Модель select
- •Модель wsaAsyncSelect
- •Модель wsaEventSelect
- •Модель перекритого введення-виведення
- •Модель портів завершення
- •Хід роботи
- •1. Запустіть VisualStudio та наберіть наступну програму
Лабораторна робота №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 для видалення даних з буфера.
Щоб цього уникнути, варто запобігти заморожуванню додатка через недолік даних (через мережні проблеми або проблеми клієнта) без постійного «підглядання» у системні мережні буфери. Один з методів — розділити додатка на читаючий та обчислювальний потоки, що спільно використають загальний буфер даних. Доступ до буфера регулюється синхронізуючим об'єктом, таким як подія або мютекс Завдання потоку, що зчитує, - постійно читати дані з мережі й перешкодити їх у загальний буфер. Зчитавши мінімально необхідну кількість даних, цей потік ініціює сигнальну подію, що повідомляє потік, що обчислює, що можна починати обчислення. Потім, обчислюючий потік видаляє частину даних з буфера й робить із ними необхідні операції. Недолік блокування сокетів - додатку важко підтримувати зв'язок по декількох сокетах одночасно. Наведену схему можна змінити, щоб потоки створювалися окремо для кожного сокета.
