Partager via


Réception de données sur un socket Connection-Oriented

Une fois qu’une application WSK (Winsock Kernel) a connecté un socket orienté connexion à une adresse de transport distante, elle peut recevoir des données sur le socket. Une application WSK peut également recevoir des données sur un socket orienté connexion qu’elle a accepté sur un socket d’écoute. Une application WSK reçoit des données sur un socket orienté connexion en appelant la fonction WskReceive .

L’exemple de code suivant montre comment une application WSK peut recevoir des données sur un socket orienté connexion.

// Prototype for the receive IoCompletion routine
NTSTATUS
  ReceiveComplete(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp,
    PVOID Context
    );

// Function to receive data
NTSTATUS
  ReceiveData(
    PWSK_SOCKET Socket,
    PWSK_BUF DataBuffer
    )
{
  PWSK_PROVIDER_CONNECTION_DISPATCH Dispatch;
  PIRP Irp;
  NTSTATUS Status;

  // Get pointer to the provider dispatch structure
  Dispatch =
    (PWSK_PROVIDER_CONNECTION_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,
    ReceiveComplete,
    DataBuffer,  // Use the data buffer for the context
    TRUE,
    TRUE,
    TRUE
    );

  // Initiate the receive operation on the socket
  Status =
    Dispatch->WskReceive(
      Socket,
      DataBuffer,
      0,  // No flags are specified
      Irp
      );

  // Return the status of the call to WskReceive()
  return Status;
}

// Receive IoCompletion routine
NTSTATUS
  ReceiveComplete(
    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 data
    ...
  }

  // 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 WskReceive pour recevoir des données sur un socket orienté connexion, une application WSK peut activer la fonction de rappel d’événement WskReceiveEvent sur le socket. Si une application WSK active la fonction de rappel d’événement WskReceiveEvent sur un socket orienté connexion, le sous-système WSK appelle la fonction de rappel d’événement WskReceiveEvent du socket chaque fois que de nouvelles données sont reçues sur le socket. Pour plus d’informations sur l’activation de la fonction de rappel d’événement WskReceiveEvent d’un socket orienté connexion, 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 données par le sous-système WSK appelant la fonction de rappel d’événement WskReceiveEvent d’un socket orienté connexion.

// A connection-oriented socket's WskReceiveEvent
// event callback function
NTSTATUS WSKAPI
  WskReceiveEvent(
    PVOID SocketContext,
    ULONG Flags,
    PWSK_DATA_INDICATION DataIndication,
    SIZE_T BytesIndicated,
    SIZE_T *BytesAccepted
    )
{
  // 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 data was received
    return STATUS_SUCCESS;
  }

  // Error
  else
  {
    // Close the socket
    ...

    // Return success since no data was indicated
    return STATUS_SUCCESS;
  }
}

Si la fonction de rappel d’événement WskReceiveEvent d’un socket orienté connexion ne récupère pas toutes les données contenues dans la liste des structures WSK_DATA_INDICATION pointées par 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 remettre la liste des structures WSK_DATA_INDICATION dans le sous-système WSK une fois qu’il a récupéré toutes les données des structures de la liste.

Si la fonction de rappel d’événement WskReceiveEvent d’un socket orienté connexion n’accepte qu’une partie du nombre total d’octets de données reçues, elle doit définir la variable vers laquelle pointe le paramètre BytesAccepted sur le nombre d’octets de données réellement acceptés. Toutefois, si la fonction de rappel d’événement WskReceiveEvent du socket accepte toutes les données reçues, elle n’a pas besoin de définir la variable vers laquelle pointe le paramètre BytesAccepted .