Udostępnij za pośrednictwem


Odbieranie danych za pośrednictwem gniazda do datagramów

Gdy aplikacja jądra Winsock (WSK) powiąże gniazdo datagramu z lokalnym adresem transportowym, może odbierać datagramy przez gniazdo. Aplikacja WSK odbiera datagram za pośrednictwem gniazda datagramu, wywołując funkcję WskReceiveFrom.

Poniższy przykład kodu pokazuje, jak aplikacja WSK może odbierać datagram za pośrednictwem gniazda datagramu.

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

Alternatywnie do wywoływania funkcji WskReceiveFrom w celu odbierania każdego datagramu za pośrednictwem gniazda datagramu, aplikacja WSK może włączyć funkcję obsługi zdarzeń zwrotnego wywołania WskReceiveFromEvent dla gniazda. Jeśli aplikacja WSK włącza funkcję wywołania zwrotnego zdarzenia WskReceiveFromEvent na gnieździe datagramu, podsystem WSK wywołuje funkcję wywołania zwrotnego zdarzenia WskReceiveFromEvent za każdym razem, gdy nowe datagramy są odbierane na gnieździe. pl-PL: Aby uzyskać więcej informacji na temat włączania funkcji wywołania zwrotnego zdarzenia gniazda datagramu WskReceiveFromEvent, zobacz Włączanie i wyłączanie funkcji wywołania zwrotnego zdarzeń.

Poniższy przykład kodu pokazuje, jak aplikacja WSK może odbierać datagramy za pośrednictwem podsystemu WSK, wywołując funkcję zwrotną zdarzenia WskReceiveFromEvent gniazda datagramowego.

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

Jeśli funkcja wywołania zwrotnegozdarzeńWskReceiveFromEvent gniazda datagramu nie pobierze wszystkich datagramów z listy struktur WSK_DATAGRAM_INDICATION wskazywanych przez parametr DataIndication, może zachować tę listę do dalszego przetwarzania, zwracając STATUS_PENDING. W takiej sytuacji aplikacja WSK musi wywołać funkcję WskRelease, aby zwrócić listę struktur WSK_DATAGRAM_INDICATION do podsystemu WSK, gdy zakończy pobieranie wszystkich datagramów ze struktur znajdujących się na tej liście.