Выполнение управляющих операций с сокетом
После успешного создания сокета приложением Winsock Kernel (WSK) оно может выполнять операции управления сокетом. Операции управления, которые можно выполнять с сокетом, включают настройку и получение параметров сокета, а также выполнение операций IOCTL сокета.
Приложение WSK выполняет операции управления с сокетом, вызывая функцию WskControlSocket . На функцию WskControlSocket указывает член WskControlSocket структуры диспетчеризации поставщика сокета. На структуру диспетчеризации поставщика сокета указывает элемент Dispatch структуры объекта сокета ( WSK_SOCKET), возвращенный подсистемой WSK во время создания сокета.
В следующем примере кода показано, как приложение WSK может задать параметр сокета SO_EXCLUSIVEADDRUSE в сокете datagram.
// Prototype for the control socket IoCompletion routine
NTSTATUS
ControlSocketComplete(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context
);
// Function to set the SO_EXCLUSIVEADDRUSE socket option
// on a datagram socket
NTSTATUS
SetExclusiveAddrUse(
PWSK_SOCKET Socket
)
{
PWSK_PROVIDER_DATAGRAM_DISPATCH Dispatch;
PIRP Irp;
ULONG SocketOptionState;
NTSTATUS Status;
// Get pointer to the socket's provider dispatch structure
Dispatch =
(PWSK_PROVIDER_DATAGRAM_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,
ControlSocketComplete,
Socket, // Use the socket object for the context
TRUE,
TRUE,
TRUE
);
// Set the socket option state to 1 to set the socket option
SocketOptionState = 1;
// Initiate the control operation on the socket
Status =
Dispatch->WskControlSocket(
Socket,
WskSetOption,
SO_EXCLUSIVEADDRUSE,
SOL_SOCKET,
sizeof(ULONG),
&SocketOptionState,
0,
NULL,
NULL,
Irp
);
// Return the status of the call to WskControlSocket()
return Status;
}
// Control socket IoCompletion routine
NTSTATUS
ControlSocketComplete(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context
)
{
UNREFERENCED_PARAMETER(DeviceObject);
PWSK_SOCKET Socket;
// Check the result of the control operation
if (Irp->IoStatus.Status == STATUS_SUCCESS)
{
// Get the socket object from the context
Socket = (PWSK_SOCKET)Context;
// Perform the next operation on the socket
...
}
// 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.
В следующем примере кода показано, как приложение WSK может выполнять операцию IOCTL сокета SIO_WSK_SET_REMOTE_ADDRESS в сокете датаграммы.
// Prototype for the control socket IoCompletion routine
NTSTATUS
ControlSocketComplete(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context
);
// Function to perform the SIO_WSK_SET_REMOTE_ADDRESS socket
// IOCTL operation on a datagram socket
NTSTATUS
SetRemoteAddress(
PWSK_SOCKET Socket,
PSOCKADDR RemoteAddress
)
{
PWSK_PROVIDER_DATAGRAM_DISPATCH Dispatch;
PIRP Irp;
NTSTATUS Status;
// Get pointer to the socket's provider dispatch structure
Dispatch =
(PWSK_PROVIDER_DATAGRAM_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,
ControlSocketComplete,
Socket, // Use the socket object for the context
TRUE,
TRUE,
TRUE
);
// Initiate the IOCTL operation on the socket
Status =
Dispatch->WskControlSocket(
Socket,
WskIoctl,
SIO_WSK_SET_REMOTE_ADDRESS,
0,
sizeof(SOCKADDR_IN), // AF_INET
RemoteAddress,
0,
NULL,
NULL,
Irp
);
// Return the status of the call to WskControlSocket()
return Status;
}
// Control socket IoCompletion routine
NTSTATUS
ControlSocketComplete(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context
)
{
UNREFERENCED_PARAMETER(DeviceObject);
PWSK_SOCKET Socket;
// Check the result of the control operation
if (Irp->IoStatus.Status == STATUS_SUCCESS)
{
// Get the socket object from the context
Socket = (PWSK_SOCKET)Context;
// Perform the next operation on the socket
...
}
// 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;
}
Дополнительные сведения о каждой из поддерживаемых операций IOCTL сокетов см. в разделе Операции WSK Socket IOCTL.