Как упоминалось ранее, функция pipe , создает два дескриптора файлов для начала и конца канала. Каналы ограничены, потому что дескрипторы файлов используются только связанными процессами и потому что взаимодействие однонаправлено. Функция socketpair создает два дескриптора файлов для двух сокетов, подключенных на одном компьютере. Эти дескрипторы файлов разрешают двухстороннее взаимодействие двух связанных процессов. Первые три параметра команды - идентичны параметрам команды socket : они определяют домен, стиль подключения и протокол. Последний параметр - массив с двумя целыми числами, в котором хранятся характеристики файлов этих двух сокетов. При использовании команды socketpair , необходимо определить PF_LOCAL как пространство имен.
38 создание канала связи
Если вы собираетесь передавать датаграммные сообщения при помощи протокола негарантированной доставки UDP , канал связи не нужен. Сразу после создания сокетов и их инициализации можно приступать к передаче данных. Но для передачи данных с использованием протокола TCP необходимо создать канал связи.
Рассмотрим процедуру создания канала связи со стороны сервера.
Прежде всего вы должны переключить сокет в режим приема для выполнения ожидания соединения с клиентом при помощи функции listen:
int listen(SOCKET sock, int backlog);
Через параметр sock функции необходимо передать дескриптор сокета, который будет использован для создания канала. Параметр backlog задает максимальный размер очереди для ожидания соединения (можно указывать значения от 1 до 5). Очередь содержит запросы на установку соединений для каждой пары значений (адрес IP, порт).
Ниже мы привели список возможных кодов ошибок для функции listen.
Код ошибки
Описание
WSANOTINITIALISED
Перед использованием функции необходимо вызвать функцию WSAStartup
WSAENETDOWN
Сбой в сети
WSAEADDRINUSE
Указанный адрес уже используется
WSAEINPROGRESS
Выполняется блокирующая функция интерфейсаWindows Sockets
WSAEINVAL
Сокет еще не был привязан к адресу или уже находится в подключенном состоянии
WSAEISCONN
Сокет уже находится в подключенном состоянии
WSAEMFILE
Недостаточно дескрипторов файлов
WSAENOBUFS
Нет места для размещения буфера
WSAENOTSOCK
Указанный в параметре дескриптор не является сокетом
WSAEOPNOTSUPP
Функция listen не работает с сокетом указанного типа
Ниже мы привели пример вызов функции listen:
if(listen(srv_socket , 1) == SOCKET_ERROR )
{
closesocket (srv_socket);
MessageBox(NULL, "listen Error", "Error", MB_OK);
return;
}
Далее необходимо выполнить ожидание соединения. Это можно выполнить двумя различными способами.
Первый способ заключается в циклическом вызове функции accept до тех пор, пока не будет установлено соединение. Затем можно будет приступать к обмену данными.
Функция accept имеет следующий прототип:
SOCKET accept (SOCKET sock, struct sockaddr FAR * addr,
int FAR * addrlen);
Через параметр sock необходимо указать дескриптор сокета, который находится в режиме приема для выполнения ожидания.
Параметр addr должен содержать адрес буфера, в который будет записан адрес узла, подключившегося к серверу. Размер этого буфера необходимо указать в переменной типа int, адрес которой передается через параметр addrlen.
Если ожидание соединения в цикле не вызывает у вас особого энтузиазма, можно предложить более удобный способ, основанный на использовании расширения программного интерфейса Windows Socket, предназначенного для выполнения асинхронных операций.
Приведем список возможных кодов ошибок для функции accept.
Код ошибки
Описание
WSANOTINITIALISED
Перед использованием функции необходимо вызвать функцию WSAStartup
WSAENETDOWN
Сбой в сети
WSAEFAULT
Значение параметраaddrlen меньше размера структуры адреса
WSAEINTR
Работа функции была отменена при помощи функции WSACancelBlockingCall
WSAEINPROGRESS
Выполняется блокирующая функция интерфейсаWindows Sockets
WSAEINVAL
Перед вызовом функции accept не была вызывана функция listen
WSAEMFILE
Нет доступных дескрипторов
WSAENOBUFS
Установлено слишком много соединений
WSAENOTSOCK
Указанный в параметре дескриптор не является сокетом
WSAEOPNOTSUPP
Данный тип сокета нельзя использовать при вызове функций, ориентированных на работу с каналом связи
WSAEWOULDBLOCK
Сокет отмечен как неблокирующий и в настоящее время нет каналов связи, которые нужно устанавливать
Вместо того чтобы ожидать соединение, вызывая в цикле функцию accept , ваше приложение может вызвать один раз функцию WSAAsyncSelect , указав ей, что при получении запроса на установку соединения функция окна вашего приложения должна получить сообщение:
#define WSA_ACCEPT (WM_USER + 1)
// При попытке установки соединения главное окно приложения
В данном случае ожидание соединения выполняется для сокета srv_socket . Последний параметр функции имеет значение FD_ACCEPT . Это означает, что при попытке создания канала связи функция окна с идентификатором hWnd получит сообщение WSA_ACCEPT, определенное в вашем приложении.
Обработчик этого сообщения может выглядеть, например, следующим образом:
В данном случае обработчик сообщения вначале вызывает функцию accept , выполняющую создание канала передачи данных. После этого функция WSAAsyncSelect вызывается еще один раз для того чтобы установить асинхронную обработку приема данных от удаленного клиента, а также обработку ситуации разрыва канала связи.