データグラム ソケット経由でのデータの受信
Winsock カーネル (WSK) アプリケーションは、データグラム ソケットをローカル トランスポート アドレスにバインドした後、ソケット経由でデータグラムを受信できます。 WSK アプリケーションは、WskReceiveFrom 関数を呼び出して、データグラム ソケット経由でデータグラムを受信します。
次のコード例は、WSK アプリケーションがデータグラム ソケット経由でデータグラムを受信する方法を示しています。
// Prototype for the receive datagram IoCompletion routine
NTSTATUS
ReceiveDatagramComplete(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context
);
// Function to receive a datagram
NTSTATUS
ReceiveDatagram(
PWSK_SOCKET Socket,
PWSK_BUF DatagramBuffer
)
{
PWSK_PROVIDER_DATAGRAM_DISPATCH Dispatch;
PIRP Irp;
NTSTATUS Status;
// Get pointer to the 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,
ReceiveDatagramComplete,
DatagramBuffer, // Use the datagram buffer for the context
TRUE,
TRUE,
TRUE
);
// Initiate the receive operation on the socket
Status =
Dispatch->WskReceiveFrom(
Socket,
DatagramBuffer,
0, // No flags are specified
NULL, // Not interested in the remote address
NULL, // Not interested in any associated control information
NULL,
NULL,
Irp
);
// Return the status of the call to WskReceiveFrom()
return Status;
}
// Receive datagram IoCompletion routine
NTSTATUS
ReceiveDatagramComplete(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context
)
{
UNREFERENCED_PARAMETER(DeviceObject);
PWSK_BUF DataBuffer;
ULONG ByteCount;
// Check the result of the receive operation
if (Irp->IoStatus.Status == STATUS_SUCCESS)
{
// Get the pointer to the data buffer
DataBuffer = (PWSK_BUF)Context;
// Get the number of bytes received
ByteCount = (ULONG)(Irp->IoStatus.Information);
// Process the received datagram
...
}
// 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;
}
WskReceiveFrom 関数を呼び出してデータグラム ソケット経由で各データグラムを受信する代わりに、WSK アプリケーションはソケットで WskReceiveFromEvent イベント コールバック関数を有効にすることができます。 WSK アプリケーションがデータグラム ソケットで WskReceiveFromEvent イベント コールバック関数を有効にした場合、WSK サブシステムは、ソケットで新しいデータグラムを受信するたびに、ソケットの WskReceiveFromEvent イベント コールバック関数を呼び出します。 データグラム ソケットの WskReceiveFromEvent イベント コールバック関数を有効にする方法について詳しくは、「イベント コールバック関数の有効化と無効化」をご覧ください。
次のコード例は、データグラム ソケットの WskReceiveFromEvent イベント コールバック関数を呼び出すことによって、WSK アプリケーションが WSK サブシステムによってデータグラムを受信する方法を示しています。
// A datagram socket's WskReceiveFromEvent
// event callback function
NTSTATUS WSKAPI
WskReceiveFromEvent(
PVOID SocketContext,
ULONG Flags,
PWSK_DATAGRAM_INDICATION DataIndication
)
{
// Check for a valid data indication
if (DataIndication != NULL)
{
// Loop through the list of data indication structures
while (DataIndication != NULL)
{
// Process the data in the data indication structure
...
// Move to the next data indication structure
DataIndication = DataIndication->Next;
}
// Return status indicating the datagrams were received
return STATUS_SUCCESS;
}
// Error
else
{
// Close the socket
...
// Return success since no datagrams were indicated
return STATUS_SUCCESS;
}
}
データグラム ソケットの WskReceiveFromEvent イベント コールバック関数が、DataIndication パラメーターによってポイントされる WSK_DATAGRAM_INDICATION 構造のリストからデータグラムをすべては取得しない場合は、STATUS_PENDING を返すことによってリストを保持してさらに処理することができます。 このような状況では、WSK アプリケーションは WskRelease 関数を呼び出し、リスト内の構造からすべてのデータグラムの取得を完了した後、WSK_DATAGRAM_INDICATION 構造のリストを WSK サブシステムに解放する必要があります。