次の方法で共有


データグラム ソケット経由でのデータの受信

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 サブシステムに解放する必要があります。