Partager via


Réception de données via un socket datagramme

Une fois qu’une application WSK (Winsock Kernel) a lié un socket de datagramme à une adresse de transport locale, elle peut recevoir des datagrammes sur le socket. Une application WSK reçoit un datagramme sur un socket de datagramme en appelant la fonction WskReceiveFrom .

L’exemple de code suivant montre comment une application WSK peut recevoir un datagramme sur un socket de datagramme.

// 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;
}

En guise d’alternative à l’appel de la fonction WskReceiveFrom pour recevoir chaque datagramme sur un socket de datagramme, une application WSK peut activer la fonction de rappel d’événement WskReceiveFromEvent sur le socket. Si une application WSK active la fonction de rappel d’événement WskReceiveFromEvent sur un socket de datagramme, le sous-système WSK appelle la fonction de rappel d’événement WskReceiveFromEvent du socket chaque fois que de nouveaux datagrammes sont reçus sur le socket. Pour plus d’informations sur l’activation de la fonction de rappel d’événement WskReceiveFromEvent d’un socket de datagramme, consultez Activation et désactivation des fonctions de rappel d’événements.

L’exemple de code suivant montre comment une application WSK peut recevoir des datagrammes par le sous-système WSK en appelant la fonction de rappel d’événement WskReceiveFromEvent d’un socket de datagramme.

// 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;
  }
}

Si la fonction de rappel d’événement WskReceiveFromEvent d’un socket de datagramme ne récupère pas tous les datagrammes de la liste des structures WSK_DATAGRAM_INDICATION pointées vers le paramètre DataIndication , elle peut conserver la liste pour un traitement ultérieur en retournant STATUS_PENDING. Dans ce cas, l’application WSK doit appeler la fonction WskRelease pour libérer la liste des structures WSK_DATAGRAM_INDICATION dans le sous-système WSK une fois qu’elle a terminé la récupération de tous les datagrammes des structures de la liste.