Fonction WSASend (winsock2.h)
La fonction WSASend envoie des données sur un socket connecté.
Syntaxe
int WSAAPI WSASend(
[in] SOCKET s,
[in] LPWSABUF lpBuffers,
[in] DWORD dwBufferCount,
[out] LPDWORD lpNumberOfBytesSent,
[in] DWORD dwFlags,
[in] LPWSAOVERLAPPED lpOverlapped,
[in] LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
Paramètres
[in] s
Descripteur qui identifie un socket connecté.
[in] lpBuffers
Pointeur vers un tableau de structures WSABUF . Chaque structure WSABUF contient un pointeur vers une mémoire tampon et la longueur, en octets, de la mémoire tampon. Pour une application Winsock, une fois que la fonction WSASend est appelée, le système possède ces mémoires tampons et l’application peut ne pas y accéder. Ce tableau doit rester valide pendant toute la durée de l’opération d’envoi.
[in] dwBufferCount
Nombre de structures WSABUF dans le tableau lpBuffers .
[out] lpNumberOfBytesSent
Pointeur vers le nombre, en octets, envoyé par cet appel si l’opération d’E/S se termine immédiatement.
Utilisez NULL pour ce paramètre si le paramètre lpOverlapped n’est pas NULL pour éviter des résultats potentiellement erronés. Ce paramètre ne peut être NULL que si le paramètre lpOverlapped n’est pas NULL.
[in] dwFlags
Indicateurs utilisés pour modifier le comportement de l’appel de fonction WSASend . Pour plus d’informations, consultez Utilisation de dwFlags dans la section Remarques.
[in] lpOverlapped
Pointeur vers une structure WSAOVERLAPPED . Ce paramètre est ignoré pour les sockets non survolés.
[in] lpCompletionRoutine
Type : _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE
Pointeur vers la routine d’achèvement appelée lorsque l’opération d’envoi est terminée. Ce paramètre est ignoré pour les sockets non survolés.
Valeur retournée
Si aucune erreur ne se produit et que l’opération d’envoi est terminée immédiatement, WSASend retourne zéro. Dans ce cas, la routine d’achèvement a déjà été planifiée pour être appelée une fois que le thread appelant est à l’état alertable. Sinon, une valeur de SOCKET_ERROR est retournée et un code d’erreur spécifique peut être récupéré en appelant WSAGetLastError. Le code d’erreur WSA_IO_PENDING indique que l’opération qui se chevauche a été lancée avec succès et que l’achèvement sera indiqué ultérieurement. Tout autre code d’erreur indique que l’opération qui se chevauche n’a pas été lancée avec succès et qu’aucune indication d’achèvement ne se produira.
Code d'erreur | Signification |
---|---|
Le circuit virtuel a été interrompu en raison d'un délai d'attente ou d'un autre échec. | |
Pour un socket de flux, le circuit virtuel a été réinitialisé par le côté distant. L’application doit fermer le socket, car il n’est plus utilisable. Pour un socket de datagramme UDP, cette erreur indique qu’une opération d’envoi précédente a entraîné un message ICMP « Port inaccessible ». | |
Le paramètre lpBuffers, lpNumberOfBytesSent, lpOverlapped, lpCompletionRoutine n’est pas totalement contenu dans une partie valide de l’espace d’adressage utilisateur. | |
Un appel bloquant Windows Socket 1.1 a été annulé via WSACancelBlockingCall. | |
Un appel bloquant Windows Sockets 1.1 est en cours ou le fournisseur de services traite toujours une fonction de rappel. | |
Le socket n’a pas été lié à bind ou le socket n’est pas créé avec l’indicateur qui se chevauche. | |
Le socket est orienté message et le message est plus grand que le maximum pris en charge par le transport sous-jacent. | |
Le sous-système réseau a échoué. | |
Pour un socket de flux, la connexion a été interrompue en raison d’une activité de maintien en vie détectant un échec alors que l’opération était en cours. Pour un socket datagramme, cette erreur indique que la durée de vie (TTL, Time to Live) a expiré. | |
Le fournisseur Windows Sockets signale un interblocage de mémoire tampon. | |
Le socket n'est pas connecté. | |
Le descripteur n’est pas un socket. | |
MSG_OOB a été spécifié, mais le socket n’est pas de type flux tel que le type SOCK_STREAM, les données OOB ne sont pas prises en charge dans le domaine de communication associé à ce socket, MSG_PARTIAL n’est pas pris en charge, ou le socket est unidirectionnel et prend uniquement en charge les opérations de réception. | |
Le socket a été arrêté ; il n’est pas possible d’utiliser WSASend sur un socket une fois l’arrêt appelé avec la valeur définie sur SD_SEND ou SD_BOTH. | |
Windows NT :
Sockets qui se chevauchent : il y a trop de demandes d’E/S qui se chevauchent. Sockets non bloqués : le socket est marqué comme non bloquant et l’opération d’envoi ne peut pas être effectuée immédiatement. |
|
Un appel WSAStartup réussi doit se produire avant d’utiliser cette fonction. | |
Une opération qui se chevauche a été lancée avec succès et l’achèvement sera indiqué ultérieurement. | |
L’opération qui se chevauche a été annulée en raison de la fermeture du socket, de l’exécution de la commande « SIO_FLUSH » dans WSAIoctl ou du thread qui a lancé la demande superposée a été arrêté avant la fin de l’opération. Pour plus d'informations, consultez la section Notes. |
Notes
La fonction WSASend fournit des fonctionnalités au-delà de la fonction d’envoi standard dans deux domaines importants :
- Il peut être utilisé conjointement avec des sockets qui se chevauchent pour effectuer des opérations d’envoi qui se chevauchent.
- Il permet de spécifier plusieurs mémoires tampons d’envoi , ce qui le rend applicable au type scatter/collect d’E/S.
Un socket créé par la fonction socket aura l’attribut superposé comme valeur par défaut. Un socket créé par la fonction WSASocket avec le paramètre dwFlags passé à WSASocket avec le WSA_FLAG_OVERLAPPED jeu de bits aura l’attribut superposé. Pour les sockets avec l’attribut superposé, WSASend utilise les E/S qui se chevauchent, sauf si les paramètres lpOverlapped et lpCompletionRoutine sont NULL. Dans ce cas, le socket est traité comme un socket qui ne se chevauche pas. Une indication d’achèvement se produit, appelant l’achèvement d’une routine ou d’un paramètre d’un objet d’événement, lorsque la ou les mémoires tampons ont été consommées par le transport. Si l’opération ne se termine pas immédiatement, la status d’achèvement finale est récupérée via la routine d’achèvement ou WSAGetOverlappedResult.
Si lpOverlapped et lpCompletionRoutine ont la valeur NULL, le socket de cette fonction sera traité comme un socket non superposé.
Pour les sockets non superposés, les deux derniers paramètres (lpOverlapped, lpCompletionRoutine) sont ignorés et WSASend adopte la même sémantique de blocage que l’envoi. Les données sont copiées à partir de la ou des mémoires tampons dans la mémoire tampon du transport. Si le socket n’est pas bloquant et orienté flux, et qu’il n’y a pas suffisamment d’espace dans la mémoire tampon du transport, WSASend retourne avec seulement une partie des mémoires tampons de l’application ayant été consommées. Étant donné la même situation de mémoire tampon et un socket bloquant, WSASend bloque jusqu’à ce que tout le contenu de la mémoire tampon d’application ait été consommé.
Pour les sockets orientés message, ne dépassez pas la taille de message maximale du fournisseur sous-jacent, qui peut être obtenue en obtenant la valeur de l’option de socket SO_MAX_MSG_SIZE. Si les données sont trop longues pour passer par le protocole sous-jacent, l’erreur WSAEMSGSIZE est retournée et aucune donnée n’est transmise.
Windows Me/98/95 : La fonction WSASend ne prend pas en charge plus de 16 mémoires tampons.
Utilisation de dwFlags
Le paramètre dwFlags peut être utilisé pour influencer le comportement de l’appel de fonction au-delà des options spécifiées pour le socket associé. Autrement dit, la sémantique de cette fonction est déterminée par les options de socket et le paramètre dwFlags . Ce dernier est construit à l’aide de l’opérateur OR au niveau du bit avec l’une des valeurs répertoriées dans le tableau suivant.Valeur | Signification |
---|---|
MSG_DONTROUTE | Spécifie que les données ne doivent pas faire l’objet d’un routage. Un fournisseur de services Windows Sockets peut choisir d’ignorer cet indicateur. |
MSG_OOB | Envoyer des données OOB sur un socket de type flux, tel que SOCK_STREAM uniquement. |
MSG_PARTIAL | Spécifie que lpBuffers ne contient qu’un message partiel. N’oubliez pas que le code d’erreur WSAEOPNOTSUPP sera retourné par les transports qui ne prennent pas en charge les transmissions partielles de messages. |
E/S de sockets superposées
Si une opération qui se chevauche se termine immédiatement, WSASend retourne une valeur de zéro et le paramètre lpNumberOfBytesSent est mis à jour avec le nombre d’octets envoyés. Si l’opération qui se chevauche est correctement lancée et se terminera ultérieurement, WSASend retourne SOCKET_ERROR et indique le code d’erreur WSA_IO_PENDING. Dans ce cas, lpNumberOfBytesSent n’est pas mis à jour. Lorsque l’opération qui se chevauche se termine, la quantité de données transférées est indiquée par le biais du paramètre cbTransferred dans la routine d’achèvement (si spécifié), ou via le paramètre lpcbTransfer dans WSAGetOverlappedResult.Le paramètre lpOverlapped doit être valide pendant la durée de l’opération qui se chevauche. Si plusieurs opérations d’E/S sont simultanément en attente, chacune doit référencer une structure WSAOVERLAPPED distincte.
Si le paramètre lpCompletionRoutine a la valeur NULL, le paramètre hEvent de lpOverlapped est signalé lorsque l’opération qui se chevauche se termine s’il contient un handle d’objet d’événement valide. Une application peut utiliser WSAWaitForMultipleEvents ou WSAGetOverlappedResult pour attendre ou interroger l’objet d’événement.
Si lpCompletionRoutine n’a pas la valeur NULL, le paramètre hEvent est ignoré et peut être utilisé par l’application pour transmettre des informations de contexte à la routine d’achèvement. Un appelant qui transmet un lpCompletionRoutine non NULL et appelle ultérieurement WSAGetOverlappedResult pour la même demande d’E/S qui se chevauche ne peut pas définir le paramètre fWait pour cet appel de WSAGetOverlappedResult sur TRUE. Dans ce cas, l’utilisation du paramètre hEvent n’est pas définie et une tentative d’attente sur le paramètre hEvent produit des résultats imprévisibles.
La routine d’achèvement suit les mêmes règles que celles indiquées pour les routines d’achèvement d’E/S de fichiers Windows. La routine d’achèvement n’est pas appelée tant que le thread n’est pas dans un état d’attente pouvant être alerté, comme cela peut se produire lorsque la fonction WSAWaitForMultipleEvents avec le paramètre fAlertable défini sur TRUE est appelée.
Les fournisseurs de transport permettent à une application d’appeler des opérations d’envoi et de réception à partir du contexte de la routine d’achèvement des E/S de socket et garantissent que, pour un socket donné, les routines d’achèvement des E/S ne seront pas imbriquées. Cela permet aux transmissions de données sensibles au temps de se produire entièrement dans un contexte préemptif.
L’exemple de code C++ suivant est un prototype de la routine d’achèvement.
void CALLBACK CompletionROUTINE(
IN DWORD dwError,
IN DWORD cbTransferred,
IN LPWSAOVERLAPPED lpOverlapped,
IN DWORD dwFlags
);
La fonction CompletionRoutine est un espace réservé pour un nom de fonction défini par l’application ou défini par la bibliothèque. Le paramètre dwError spécifie la status d’achèvement pour l’opération qui se chevauche, comme indiqué par lpOverlapped. cbTransferred spécifie le nombre d’octets envoyés. Actuellement, aucune valeur d’indicateur n’est définie et dwFlags est égal à zéro. Cette fonction ne retourne pas de valeur.
Le retour à partir de cette fonction permet l’appel d’une autre routine d’achèvement en attente pour ce socket. Toutes les routines d’achèvement en attente sont appelées avant que l’attente du thread pouvant être alerté soit satisfaite avec un code de retour de WSA_IO_COMPLETION. Les routines d’achèvement peuvent être appelées dans n’importe quel ordre, pas nécessairement dans le même ordre que les opérations qui se chevauchent. Toutefois, il est garanti que les mémoires tampons publiées soient envoyées dans l’ordre dans lequel elles sont spécifiées.
L’ordre des appels effectués à WSASend est également l’ordre dans lequel les mémoires tampons sont transmises à la couche de transport. WSASend ne doit pas être appelé simultanément sur le même socket orienté flux à partir de threads différents, car certains fournisseurs Winsock peuvent fractionner une demande d’envoi volumineuse en plusieurs transmissions, ce qui peut entraîner l’entrelacement involontaire de données à partir de plusieurs demandes d’envoi simultanées sur le même socket orienté flux.
Exemple de code
L’exemple de code suivant montre comment utiliser la fonction WSASend en mode d’E/S qui se chevauche.#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
// Need to link with Ws2_32.lib
#pragma comment(lib, "ws2_32.lib")
#define DATA_BUFSIZE 4096
#define SEND_COUNT 10
int __cdecl main()
{
WSADATA wsd;
struct addrinfo *result = NULL;
struct addrinfo hints;
WSAOVERLAPPED SendOverlapped;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET AcceptSocket = INVALID_SOCKET;
WSABUF DataBuf;
DWORD SendBytes;
DWORD Flags;
char buffer[DATA_BUFSIZE];
int err = 0;
int rc, i;
// Load Winsock
rc = WSAStartup(MAKEWORD(2, 2), &wsd);
if (rc != 0) {
printf("Unable to load Winsock: %d\n", rc);
return 1;
}
// Make sure the hints struct is zeroed out
SecureZeroMemory((PVOID) & hints, sizeof(struct addrinfo));
// Initialize the hints to obtain the
// wildcard bind address for IPv4
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
rc = getaddrinfo(NULL, "27015", &hints, &result);
if (rc != 0) {
printf("getaddrinfo failed with error: %d\n", rc);
return 1;
}
ListenSocket = socket(result->ai_family,
result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
return 1;
}
rc = bind(ListenSocket, result->ai_addr, (int) result->ai_addrlen);
if (rc == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
return 1;
}
rc = listen(ListenSocket, 1);
if (rc == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
return 1;
}
// Accept an incoming connection request
AcceptSocket = accept(ListenSocket, NULL, NULL);
if (AcceptSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
return 1;
}
printf("Client Accepted...\n");
// Make sure the SendOverlapped struct is zeroed out
SecureZeroMemory((PVOID) & SendOverlapped, sizeof (WSAOVERLAPPED));
// Create an event handle and setup the overlapped structure.
SendOverlapped.hEvent = WSACreateEvent();
if (SendOverlapped.hEvent == NULL) {
printf("WSACreateEvent failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
closesocket(AcceptSocket);
return 1;
}
DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = buffer;
for (i = 0; i < SEND_COUNT; i++) {
rc = WSASend(AcceptSocket, &DataBuf, 1,
&SendBytes, 0, &SendOverlapped, NULL);
if ((rc == SOCKET_ERROR) &&
(WSA_IO_PENDING != (err = WSAGetLastError()))) {
printf("WSASend failed with error: %d\n", err);
break;
}
rc = WSAWaitForMultipleEvents(1, &SendOverlapped.hEvent, TRUE, INFINITE,
TRUE);
if (rc == WSA_WAIT_FAILED) {
printf("WSAWaitForMultipleEvents failed with error: %d\n",
WSAGetLastError());
break;
}
rc = WSAGetOverlappedResult(AcceptSocket, &SendOverlapped, &SendBytes,
FALSE, &Flags);
if (rc == FALSE) {
printf("WSASend failed with error: %d\n", WSAGetLastError());
break;
}
printf("Wrote %d bytes\n", SendBytes);
WSAResetEvent(SendOverlapped.hEvent);
}
WSACloseEvent(SendOverlapped.hEvent);
closesocket(AcceptSocket);
closesocket(ListenSocket);
freeaddrinfo(result);
WSACleanup();
return 0;
}
Windows Phone 8 : cette fonction est prise en charge pour les applications Windows Phone Store sur Windows Phone 8 et versions ultérieures.
Windows 8.1 et Windows Server 2012 R2 : cette fonction est prise en charge pour les applications du Windows Store sur Windows 8.1, Windows Server 2012 R2 et versions ultérieures.
Configuration requise
Condition requise | Valeur |
---|---|
Client minimal pris en charge | Windows 8.1, Windows Vista [applications de bureau | Applications UWP] |
Serveur minimal pris en charge | Windows Server 2003 [applications de bureau | applications UWP] |
Plateforme cible | Windows |
En-tête | winsock2.h |
Bibliothèque | Ws2_32.lib |
DLL | Ws2_32.dll |