Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Когда приложение Winsock Kernel (WSK) завершило использование сокета, оно должно закрыть сокет и освободить все связанные ресурсы. Приложение WSK должно закрыть все открытые сокеты, прежде чем приложение сможет отключиться от подсистемы WSK. Дополнительные сведения об отключении приложения WSK от подсистемы WSK см. в разделе "Отмена регистрации приложения ядра Winsock".
Приложение WSK закрывает сокет, вызывая функцию WskCloseSocket . Перед вызовом функции WskCloseSocket приложение WSK должно убедиться, что на любом из потоков приложения не выполняются другие вызовы к функциям сокета, включая функции расширения. Однако приложение WSK может вызывать WskCloseSocket, если ожидающие IRP от предыдущих вызовов функций сокета еще не завершены.
Метод, который использует приложение WSK для обеспечения отсутствия других вызовов функций, выполняемых для каких-либо функций сокета перед вызовом функции WskCloseSocket , зависит от структуры приложения. Например, если приложению WSK может потребоваться закрыть сокет в одном потоке, в то время как вызовы могут выполняться для других функций сокета в одном или нескольких других потоках, то приложение обычно использует счетчик ссылок для отслеживания количества вызовов функций, которые в настоящее время выполняются в сокете. В этой ситуации приложение WSK атомарно проверяет и увеличивает счетчик ссылок сокета перед вызовом одной из функций сокета, а затем атомарно уменьшает счетчик ссылок сокета при возврате функции. Если счетчик ссылок равен нулю, приложение WSK может безопасно вызвать функцию WskCloseSocket , чтобы закрыть сокет.
С другой стороны, если проектирование приложения WSK гарантирует, что не будет никаких вызовов к функциям определенного сокета в других потоках, когда приложение вызывает функцию WskCloseSocket для закрытия сокета, то приложению WSK не нужно использовать счетчик ссылок для отслеживания выполняющихся в данный момент вызовов функций на сокете. Например, если приложение WSK выполняет все операции сокета для определенного сокета из одного потока, приложение может безопасно вызвать функцию WskCloseSocket из этого потока без необходимости в счетчике ссылок.
Вызов функции WskCloseSocket приводит к отмене и завершению всех ожидающих IRPs от предыдущих вызовов функций сокета. Подсистема WSK также гарантирует, что любые выполняющиеся функции обратного вызова событий вернули управление обратно в подсистему WSK до завершения операции закрытия.
В следующем примере кода показано, как приложение WSK может закрыть сокет.
// Prototype for the socket close IoCompletion routine
NTSTATUS
CloseSocketComplete(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context
);
// Function to close a socket
NTSTATUS
CloseSocket(
PWSK_SOCKET Socket,
PWSK_APP_SOCKET_CONTEXT SocketContext
)
{
PWSK_PROVIDER_BASIC_DISPATCH Dispatch;
PIRP Irp;
NTSTATUS Status;
// Get pointer to the socket's provider dispatch structure
Dispatch =
(PWSK_PROVIDER_BASIC_DISPATCH)(Socket->Dispatch);
// Allocate an IRP
Irp =
IoAllocateIrp(
1,
FALSE
);
// Check result
if (!Irp)
{
// Return error
return STATUS_INSUFFICIENT_RESOURCES;
}
// Set the completion routine for the IRP
IoSetCompletionRoutine(
Irp,
CloseSocketComplete,
SocketContext,
TRUE,
TRUE,
TRUE
);
// Initiate the close operation on the socket
Status =
Dispatch->WskCloseSocket(
Socket,
Irp
);
// Return the status of the call to WskCloseSocket()
return Status;
}
// Socket close IoCompletion routine
NTSTATUS
CloseSocketComplete(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context
)
{
UNREFERENCED_PARAMETER(DeviceObject);
PWSK_APP_SOCKET_CONTEXT SocketContext;
// Check the result of the socket close operation
if (Irp->IoStatus.Status == STATUS_SUCCESS)
{
// Get the pointer to the socket context
SocketContext =
(PWSK_APP_SOCKET_CONTEXT)Context;
// Perform any cleanup and/or deallocation of the socket context
...
}
// Error status
else
{
// Handle error
...
}
// Free the IRP
IoFreeIrp(Irp);
// Always return STATUS_MORE_PROCESSING_REQUIRED to
// terminate the completion processing of the IRP.
return STATUS_MORE_PROCESSING_REQUIRED;
}
После вызова приложения WSK WskCloseSocket он не должен выполнять дальнейшие вызовы к каким-либо функциям сокета.
Если приложение WSK закрывает сокет, ориентированный на подключение, который ранее не был отключен в обоих направлениях, подсистема WSK автоматически выполняет принудительное отключение перед его закрытием. Дополнительные сведения об отключении сокета см. в разделе "Отключение сокета от назначения".