Freigeben über


Empfangen von Daten über einen Connection-Oriented Socket

Nachdem eine Winsock Kernel -Anwendung (WSK) einen verbindungsorientierten Socket mit einer Remotetransportadresse verbunden hat, kann sie Daten über den Socket empfangen. Eine WSK-Anwendung kann auch Daten über einen verbindungsorientierten Socket empfangen, die sie an einem Listener-Socket angenommen hat. Eine WSK-Anwendung empfängt Daten über einen verbindungsorientierten Socket, indem die WskReceive-Funktion aufgerufen wird.

Das folgende Codebeispiel zeigt, wie eine WSK-Anwendung Daten über einen verbindungsorientierten Socket empfangen kann.

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

Alternativ zum Aufrufen der WskReceive--Funktion zum Empfangen von Daten über einen verbindungsorientierten Socket kann eine WSK-Anwendung die WskReceiveEvent Ereignisrückruffunktion im Socket aktivieren. Wenn eine WSK-Anwendung die WskReceiveEvent Ereignisrückruffunktion für einen verbindungsorientierten Socket aktiviert, ruft das WSK-Subsystem die WskReceiveEvent Ereignisrückruffunktion auf, wenn neue Daten im Socket empfangen werden. Weitere Informationen über die Aktivierung Ereignis-Callback-Funktion WskAcceptEvent eines verbindungsorientierten Sockets finden Sie unter Aktivieren und Deaktivieren von Ereignis-Callback-Funktionen.

Das folgende Codebeispiel zeigt, wie eine WSK-Anwendung Daten vom WSK-Subsystem empfangen kann, das die WskReceiveEvent Ereignisrückruffunktion eines verbindungsorientierten Sockets aufruft.

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

Wenn die Ereignis-Callback-FunktionWskReceiveEvent eines verbindungsorientierten Sockets nicht alle Daten abruft, die in der Liste der WSK_DATA_INDICATION-Strukturen enthalten sind, auf die der Parameter DataIndication verweist, kann sie die Liste zur weiteren Verarbeitung behalten, indem sie STATUS_PENDING zurückgibt. In diesem Fall muss die WSK-Anwendung die WskRelease Funktion aufrufen, um die Liste der WSK_DATA_INDICATION Strukturen wieder in das WSK-Subsystem zurückzugeben, nachdem alle Daten aus den Strukturen in der Liste abgerufen wurden.

Wenn die Ereignisrückruffunktion WskReceiveEvent eines verbindungsorientierten Sockets nur einen Teil der gesamten Anzahl von empfangenen Bytes akzeptiert, muss die Variable, auf die durch den Parameter BytesAccepted verwiesen wird, auf die Anzahl der tatsächlich akzeptierten Bytes festgelegt werden. Wenn die WskReceiveEvent Ereignisrückruffunktion des Sockets jedoch alle empfangenen Daten akzeptiert, muss die Variable nicht festgelegt werden, auf die der BytesAccepted-Parameter verweist.