다음을 통해 공유


Datagram 소켓을 통해 데이터 수신

Winsock Kernel(WSK) 애플리케이션이 데이터그램 소켓을 로컬 전송 주소에 바인딩한 후에는 소켓을 통해 데이터그램을 받을 수 있습니다. WSK 애플리케이션은 WskReceiveFrom 함수를 호출하여 데이터그램 소켓을 통해 데이터그램을 받습니다.

다음 코드 예제에서는 WSK 애플리케이션이 데이터그램 소켓을 통해 데이터그램을 받을 수 있는 방법을 보여 줍니다.

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

WskReceiveFrom 함수를 호출하여 데이터그램 소켓을 통해 각 데이터그램을 수신하는 대신 WSK 애플리케이션은 소켓에서 WskReceiveFromEvent 이벤트 콜백 함수를 사용하도록 설정할 수 있습니다. WSK 애플리케이션이 데이터그램 소켓 에서 WskReceiveFromEvent 이벤트 콜백 함수를 사용하도록 설정하는 경우 WSK 하위 시스템은 소켓에서 새 데이터그램을 받을 때마다 소켓의 WskReceiveFromEvent 이벤트 콜백 함수를 호출합니다. 데이터그램 소켓의 WskReceiveFromEvent 이벤트 콜백 함수를 사용하도록 설정하는 방법에 대한 자세한 내용은 이벤트 콜백 함수 사용 및 비활성화를 참조하세요.

다음 코드 예제에서는 WSK 애플리케이션이 데이터그램 소켓의 WskReceiveFromEvent 이벤트 콜백 함수를 호출하여 WSK 하위 시스템에 의해 데이터그램을 수신하는 방법을 보여 줍니다.

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

Datagram 소켓의 WskReceiveFromEvent 이벤트 콜백 함수가 DataIndication 매개 변수가 가리키는 WSK_DATAGRAM_INDICATION 구조 목록에서 모든 데이터그램을 검색하지 않는 경우 STATUS_PENDING 반환하여 추가 처리를 위해 목록을 유지할 수 있습니다. 이 경우 WSK 애플리케이션은 WskRelease 함수를 호출하여 목록의 구조체에서 모든 데이터그램 검색을 완료한 후 WSK_DATAGRAM_INDICATION 구조 목록을 WSK 하위 시스템에 다시 해제해야 합니다.