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 하위 시스템에 다시 해제해야 합니다.