Перекрывающиеся объекты ввода-вывода и событий

Windows Sockets 2 поддерживает перекрывающиеся операции ввода-вывода, и все поставщики транспорта поддерживают эту возможность. Перекрывающиеся операции ввода-вывода соответствуют модели, установленной в Windows, и могут выполняться для сокетов, созданных с помощью функции сокетов , или сокетов, созданных с помощью функции WSASocket с флагом WSA_FLAG_OVERLAPPED , установленным в параметре dwFlags .

Примечание

Создание сокета с перекрывающимся атрибутом не влияет на то, находится ли сокет в режиме блокировки или неблокировки. Сокеты, созданные с помощью атрибута перекрытия, можно использовать для выполнения перекрывающихся операций ввода-вывода— это не меняет режим блокировки сокета. Так как перекрывающиеся операции ввода-вывода не блокируются, режим блокировки сокета не имеет значения для этих операций.

 

Для получения приложения используют функции WSARecv или WSARecvFrom для предоставления буферов, в которые должны быть получены данные. Если один или несколько буферов были размещены до момента получения данных в сети, эти данные могут быть помещены в буферы пользователя сразу по мере поступления. Таким образом, он может избежать операции копирования, которая в противном случае произошла бы при вызове функции recv или recvfrom . Если данные уже присутствуют при отправке буферов получения, они немедленно копируются в буферы пользователя.

Если данные поступают, когда приложение не опубликовало буферы приема, в сети применяется знакомый синхронный стиль работы. То есть входящие данные помещается в буфер, пока приложение не вызовет прием и тем самым не предоставляет буфер, в который можно скопировать данные. Исключением являются случаи, когда приложение использует setsockopt для установки нулевого размера буфера получения. В этом случае надежные протоколы позволяют получать данные только при публикации буферов приложений, а данные по ненадежным протоколам будут потеряны.

На стороне отправки приложения используют WSASend или WSASendTo для предоставления указателей на заполненные буферы, а затем соглашаются не беспокоить буферы каким-либо образом, пока сеть не поглотит содержимое буфера.

Перекрывающиеся вызовы отправки и приема немедленно возвращаются. Возвращаемое нулевое значение указывает, что операция ввода-вывода была завершена немедленно и что соответствующее указание на завершение уже произошло. Это значит, что связанный объект события был поставлен в очередь или подпрограмма завершения была поставлена в очередь и будет выполняться, когда вызывающий поток переходит в состояние ожидания с оповещением.

Возвращаемое значение SOCKET_ERROR в сочетании с кодом ошибки WSA_IO_PENDING указывает, что перекрывающаяся операция успешно запущена и что после использования буферов отправки или завершения операции получения будет предоставлено следующее указание. Однако для сокетов в стиле байтового потока указание завершения происходит всякий раз, когда исчерпаны входящие данные, независимо от того, заполнены ли буферы. Любой другой код ошибки указывает на то, что перекрывающаяся операция не была успешно инициирована и что никаких признаков завершения не будет.

Операции отправки и получения могут перекрываться. Функции получения можно вызывать несколько раз для отправки буферов получения при подготовке к входящим данным, а функции отправки можно вызывать несколько раз, чтобы ставить в очередь несколько буферов для отправки. Хотя приложение может полагаться на серию перекрывающихся буферов отправки в указанном порядке, соответствующие указания завершения могут происходить в другом порядке. Аналогичным образом, на принимающей стороне буферы могут заполняться в порядке их поставки, но признаки завершения могут происходить в другом порядке.

Во многих случаях перекрывающиеся операции Winsock с использованием AcceptEx, ConnectEx, WSASend, WSARecv, TransmitFile и аналогичных функций можно отменить. Однако поведение не определено для дальнейшего использования сокета, который отменил невыполненные операции. Функция closesocket должна вызываться после отмены перекрывающейся операции. Поэтому для достижения наилучших результатов вместо отмены ввода-вывода напрямую следует вызывать функцию closesocket , чтобы закрыть сокет, что в конечном итоге приведет к прекращению всех ожидающих операций.

Функция отложенного завершения перекрывающихся операций ввода-вывода также доступна для WSAIoctl, которая представляет собой расширенную версию ioctlsocket.