Поделиться через


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

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

Заметка

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

 

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

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

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

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

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

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

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

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