當 Winsock Kernel (WSK) 應用程式完成使用插槽後,必須關閉插槽並釋放所有相關資源。 WSK 應用程式必須先關閉所有開啟的套接字,才能解除與 WSK 子系統的連結。 如需有關將 WSK 應用程式從 WSK 子系統中分離的詳細資訊,請參閱 取消註冊 Winsock 核心應用程式。
WSK 應用程式會呼叫 WskCloseSocket 函式來關閉套接字。 在呼叫 WskCloseSocket 函式之前,WSK 應用程式必須確保沒有其他任何函式正在使用該套接字的功能,包括應用程式其他線程中的任何擴充功能。 不過,如果先前對套接字函式的呼叫仍有未完成的暫止 IRP,WSK 應用程式可以呼叫 WskCloseSocket。
WSK 應用程式如何確保在呼叫 WskCloseSocket 函式前,沒有其他函式呼叫正在進行,取決於應用程式的設計。 例如,如果一個 WSK 應用程式可能需要在某個線程中關閉一個套接字,而同時在一個或多個其他線程中呼叫該套接字的其他函式,那麼該應用程式通常會使用參考計數器來追蹤該套接字目前正在進行中的函式呼叫數量。 在此情況下,WSK 應用程式會在呼叫套接字的其中一個函式之前,以原子方式測試並遞增套接字的參考計數器,然後在函式傳回時,以原子方式遞減套接字的參考計數器。 當參考計數器為零時,WSK 應用程式可以安全地呼叫 WskCloseSocket 函式來關閉套接字。
另一方面,如果 WSK 應用程式的設計保證當應用程式呼叫 WskCloseSocket 函式以關閉套接字時,不會有任何對特定套接字函數的正在進行的呼叫,則 WSK 應用程式不需要使用參考計數器來追蹤目前在套接字上進行中的函數調用數目。 例如,如果 WSK 應用程式從單一線程執行特定套接字的所有套接字作業,則應用程式可以從該線程內安全地呼叫 WskCloseSocket 函式,而不需要參考計數器。
呼叫 WskCloseSocket 函式會導致 WSK 子系統取消並完成所有先前針對此套接字函式呼叫而暫掛的 IRP。 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 子系統會在關閉套接字之前,自動執行該套接字的強制中斷。 如需中斷套接字連線的詳細資訊,請參閱 中斷與目的地的套接字連線。