Condividi tramite


Ricezione di dati su un socket Connection-Oriented

Dopo che un'applicazione Winsock Kernel (WSK) ha connesso un socket orientato alla connessione a un indirizzo di trasporto remoto, può ricevere dati tramite il socket. Un'applicazione WSK può anche ricevere dati su un socket orientato alla connessione accettato su un socket in ascolto. Un'applicazione WSK riceve i dati su un socket orientato alla connessione chiamando la funzione WskReceive .

Nell'esempio di codice seguente viene illustrato come un'applicazione WSK può ricevere dati tramite un socket orientato alla connessione.

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

In alternativa alla chiamata alla funzione WskReceive per ricevere dati tramite un socket orientato alla connessione, un'applicazione WSK può abilitare la funzione di callback degli eventi WskReceiveEvent sul socket. Se un'applicazione WSK abilita la funzione di callback degli eventi WskReceiveEvent in un socket orientato alla connessione, il sottosistema WSK chiama la funzione di callback dell'evento WskReceiveEvent del socket ogni volta che vengono ricevuti nuovi dati sul socket. Per altre informazioni sull'abilitazione della funzione di callback degli eventi WskReceiveEvent di un socket orientato alla connessione, vedere Abilitazione e disabilitazione delle funzioni di callback degli eventi.

Nell'esempio di codice seguente viene illustrato come un'applicazione WSK può ricevere dati dal sottosistema WSK che chiama la funzione di callback dell'evento WskReceiveEvent di un socket orientato alla connessione.

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

Se la funzione di callback dell'evento WskReceiveEvent di un socket orientato alla connessione non recupera tutti i dati contenuti nell'elenco di strutture WSK_DATA_INDICATION a cui punta il parametro DataIndication , può mantenere l'elenco per un'ulteriore elaborazione restituendo STATUS_PENDING. In questo caso, l'applicazione WSK deve chiamare la funzione WskRelease per rilasciare l'elenco delle strutture WSK_DATA_INDICATION al sottosistema WSK dopo aver completato il recupero di tutti i dati dalle strutture nell'elenco.

Se la funzione di callback dell'evento WskReceiveEvent di un socket orientato alla connessione accetta solo una parte del numero totale di byte dei dati ricevuti, deve impostare la variabile a cui punta il parametro BytesAccepted sul numero di byte di dati effettivamente accettati. Tuttavia, se la funzione di callback dell'evento WskReceiveEvent del socket accetta tutti i dati ricevuti, non è necessario impostare la variabile a cui punta il parametro BytesAccepted .