Condividi tramite


Ricezione di dati su un socket di datagrammi

Dopo che un'applicazione Winsock Kernel (WSK) ha associato un socket di datagrammi a un indirizzo di trasporto locale, può ricevere datagrammi sul socket. Un'applicazione WSK riceve un datagramma su un socket di datagrammi chiamando la funzione WskReceiveFrom .

Nell'esempio di codice seguente viene illustrato come un'applicazione WSK può ricevere un datagramma su un socket di datagrammi.

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

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

L'esempio di codice seguente illustra come un'applicazione WSK può ricevere datagrammi dal sottosistema WSK chiamando la funzione di callback dell'evento WskReceiveFromEvent di un socket di dati.

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

Se la funzione di callback dell'evento WskReceiveFromEvent di un socket di datagrammi non recupera tutti gli datagrammi dall'elenco di strutture WSK_DATAGRAM_INDICATION a cui punta il parametro DataIndication , può conservare 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_DATAGRAM_INDICATION al sottosistema WSK dopo aver completato il recupero di tutti gli datagrammi dalle strutture nell'elenco.