Réception de données sur un socket Connection-Oriented
Une fois qu’une application WSK (Winsock Kernel) a connecté un socket orienté connexion à une adresse de transport distante, elle peut recevoir des données sur le socket. Une application WSK peut également recevoir des données sur un socket orienté connexion qu’elle a accepté sur un socket d’écoute. Une application WSK reçoit des données sur un socket orienté connexion en appelant la fonction WskReceive .
L’exemple de code suivant montre comment une application WSK peut recevoir des données sur un socket orienté connexion.
// 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;
}
En guise d’alternative à l’appel de la fonction WskReceive pour recevoir des données sur un socket orienté connexion, une application WSK peut activer la fonction de rappel d’événement WskReceiveEvent sur le socket. Si une application WSK active la fonction de rappel d’événement WskReceiveEvent sur un socket orienté connexion, le sous-système WSK appelle la fonction de rappel d’événement WskReceiveEvent du socket chaque fois que de nouvelles données sont reçues sur le socket. Pour plus d’informations sur l’activation de la fonction de rappel d’événement WskReceiveEvent d’un socket orienté connexion, consultez Activation et désactivation des fonctions de rappel d’événements.
L’exemple de code suivant montre comment une application WSK peut recevoir des données par le sous-système WSK appelant la fonction de rappel d’événement WskReceiveEvent d’un socket orienté connexion.
// 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;
}
}
Si la fonction de rappel d’événement WskReceiveEvent d’un socket orienté connexion ne récupère pas toutes les données contenues dans la liste des structures WSK_DATA_INDICATION pointées par le paramètre DataIndication , elle peut conserver la liste pour un traitement ultérieur en retournant STATUS_PENDING. Dans ce cas, l’application WSK doit appeler la fonction WskRelease pour remettre la liste des structures WSK_DATA_INDICATION dans le sous-système WSK une fois qu’il a récupéré toutes les données des structures de la liste.
Si la fonction de rappel d’événement WskReceiveEvent d’un socket orienté connexion n’accepte qu’une partie du nombre total d’octets de données reçues, elle doit définir la variable vers laquelle pointe le paramètre BytesAccepted sur le nombre d’octets de données réellement acceptés. Toutefois, si la fonction de rappel d’événement WskReceiveEvent du socket accepte toutes les données reçues, elle n’a pas besoin de définir la variable vers laquelle pointe le paramètre BytesAccepted .