Ricezione di dati su un socket Connection-Oriented
Dopo che un'applicazione Winsock Kernel (WSK) ha connesso un socket orientato alla connessione a un indirizzo di trasporto remoto, può ricevere dati tramite il socket. Un'applicazione WSK può anche ricevere dati su un socket orientato alla connessione accettato su un socket in ascolto. Un'applicazione WSK riceve i dati su un socket orientato alla connessione chiamando la funzione WskReceive .
Nell'esempio di codice seguente viene illustrato come un'applicazione WSK può ricevere dati tramite un socket orientato alla connessione.
// 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;
}
In alternativa alla chiamata alla funzione WskReceive per ricevere dati tramite un socket orientato alla connessione, un'applicazione WSK può abilitare la funzione di callback degli eventi WskReceiveEvent sul socket. Se un'applicazione WSK abilita la funzione di callback degli eventi WskReceiveEvent in un socket orientato alla connessione, il sottosistema WSK chiama la funzione di callback dell'evento WskReceiveEvent del socket ogni volta che vengono ricevuti nuovi dati sul socket. Per altre informazioni sull'abilitazione della funzione di callback degli eventi WskReceiveEvent di un socket orientato alla connessione, vedere Abilitazione e disabilitazione delle funzioni di callback degli eventi.
Nell'esempio di codice seguente viene illustrato come un'applicazione WSK può ricevere dati dal sottosistema WSK che chiama la funzione di callback dell'evento WskReceiveEvent di un socket orientato alla connessione.
// 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;
}
}
Se la funzione di callback dell'evento WskReceiveEvent di un socket orientato alla connessione non recupera tutti i dati contenuti nell'elenco di strutture WSK_DATA_INDICATION a cui punta il parametro DataIndication , può mantenere l'elenco per un'ulteriore elaborazione restituendo STATUS_PENDING. In questo caso, l'applicazione WSK deve chiamare la funzione WskRelease per rilasciare l'elenco delle strutture WSK_DATA_INDICATION al sottosistema WSK dopo aver completato il recupero di tutti i dati dalle strutture nell'elenco.
Se la funzione di callback dell'evento WskReceiveEvent di un socket orientato alla connessione accetta solo una parte del numero totale di byte dei dati ricevuti, deve impostare la variabile a cui punta il parametro BytesAccepted sul numero di byte di dati effettivamente accettati. Tuttavia, se la funzione di callback dell'evento WskReceiveEvent del socket accetta tutti i dati ricevuti, non è necessario impostare la variabile a cui punta il parametro BytesAccepted .