Freigeben über


Empfangen von Daten über einen Connection-Oriented Socket

Nachdem eine WSK-Anwendung (Winsock Kernel) 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, den sie auf einem Lauschsocket akzeptiert 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;
}

Als Alternative zum Aufrufen der WskReceive-Funktion zum Empfangen von Daten über einen verbindungsorientierten Socket kann eine WSK-Anwendung die WskReceiveEvent-Ereignisrückruffunktion auf dem Socket aktivieren. Wenn eine WSK-Anwendung die WskReceiveEvent-Ereignisrückruffunktion in einem verbindungsorientierten Socket aktiviert, ruft das WSK-Subsystem die WskReceiveEvent-Ereignisrückruffunktion des Sockets auf, wenn neue Daten im Socket empfangen werden. Weitere Informationen zum Aktivieren der WskReceiveEvent-Ereignisrückruffunktion eines verbindungsorientierten Sockets finden Sie unter Aktivieren und Deaktivieren von Ereignisrückruffunktionen.

Das folgende Codebeispiel zeigt, wie eine WSK-Anwendung Daten empfangen kann, indem das WSK-Subsystem 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 WskReceiveEvent-Ereignisrückruffunktion eines verbindungsorientierten Sockets nicht alle Daten abruft, die in der Liste der WSK_DATA_INDICATION Strukturen enthalten sind, auf die der DataIndication-Parameter verweist, kann die Liste zur weiteren Verarbeitung beibehalten werden, indem STATUS_PENDING zurückgegeben wird. In diesem Fall muss die WSK-Anwendung die WskRelease-Funktion aufrufen, um die Liste der WSK_DATA_INDICATION Strukturen wieder an das WSK-Subsystem freizugeben, nachdem alle Daten aus den Strukturen in der Liste abgerufen wurden.

Wenn die WskReceiveEvent-Ereignisrückruffunktion eines verbindungsorientierten Sockets nur einen Teil der Gesamtanzahl der empfangenen Daten akzeptiert, muss die Variable, auf die der BytesAccepted-Parameter verweist, auf die Anzahl der Tatsächlich akzeptierten Daten 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.