Příjem dat přes soket Connection-Oriented
Jakmile aplikace rozhraní Winsock Kernel (WSK) připojí soket orientovaný na připojení ke vzdálené adrese přenosu, může přijímat data přes soket. Aplikace WSK může také přijímat data přes spojově orientovaný soket, který přijala na naslouchajícím soketu. Aplikace WSK přijímá data přes soket orientovaný na připojení voláním funkce WskReceive.
Následující příklad kódu ukazuje, jak aplikace WSK může přijímat data přes soket orientovaný na připojení.
// 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;
}
Jako alternativu k volání funkce WskReceive pro přijetí dat přes soket orientovaný na připojení, může aplikace WSK na tomto soketu povolit funkci zpětného volání události WskReceiveEvent. Pokud aplikace WSK povolí funkci zpětného volání událostí WskReceiveEvent funkci zpětného volání událostí v soketu orientovaném na připojení, subsystém WSK volá WskReceiveEvent funkci zpětného volání událostí při každém přijetí nových dat na soketu. Další informace o povolení obslužné funkce události WskReceiveEvent najdete v tématu Povolení a zakázání funkcí zpětného volání událostí.
Následující příklad kódu ukazuje, jak aplikace WSK může přijímat data pomocí volání funkce zpětného volání události WskReceiveEvent subsystému WSK na soketu orientovaném na spojení.
// 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;
}
}
Pokud funkce zpětného volání události WskReceiveEvent pro spojově orientovaný socket nezíská všechna data obsažená v seznamu struktur WSK_DATA_INDICATION, na které odkazuje parametr DataIndication, může seznam pro další zpracování zachovat tak, že vrátí hodnotu STATUS_PENDING. V takovém případě musí aplikace WSK volat funkci WskRelease, aby po dokončení načítání všech dat ze struktur v seznamu uvolnila seznam WSK_DATA_INDICATION struktur zpět do subsystému WSK.
Pokud funkce zpětného volání události WskReceiveEvent u soketu orientovaného na připojení přijme jen část z celkového počtu bajtů přijatých dat, musí nastavit proměnnou, na kterou odkazuje BytesAccepted parametr na počet bajtů dat, která byla skutečně přijata. Pokud však funkce zpětného volání události WskReceiveEvent přijímá všechna přijatá data, není nutné nastavit proměnnou, na kterou odkazuje parametr BytesAccepted.