Fonction WSASendTo (winsock2.h)
La fonction WSASendTo envoie des données à une destination spécifique, en utilisant des E/S superposées, le cas échéant.
Syntaxe
int WSAAPI WSASendTo(
[in] SOCKET s,
[in] LPWSABUF lpBuffers,
[in] DWORD dwBufferCount,
[out] LPDWORD lpNumberOfBytesSent,
[in] DWORD dwFlags,
[in] const sockaddr *lpTo,
[in] int iTolen,
[in] LPWSAOVERLAPPED lpOverlapped,
[in] LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
Paramètres
[in] s
Descripteur identifiant un socket (éventuellement connecté).
[in] lpBuffers
Pointeur vers un tableau de structures WSABUF . Chaque structure WSABUF contient un pointeur vers une mémoire tampon et la longueur de la mémoire tampon, en octets. Pour une application Winsock, une fois que la fonction WSASendTo 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 d’octets envoyés 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 peut être NULL uniquement si le paramètre lpOverlapped n’est pas NULL.
[in] dwFlags
Indicateurs utilisés pour modifier le comportement de l’appel de fonction WSASendTo .
[in] lpTo
Pointeur facultatif vers l’adresse du socket cible dans la structure SOCKADDR .
[in] iTolen
Taille, en octets, de l’adresse dans le paramètre lpTo .
[in] lpOverlapped
Pointeur vers une structure WSAOVERLAPPED (ignoré pour les sockets non inexploités).
[in] lpCompletionRoutine
Type : _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE
Pointeur vers la routine d’achèvement appelée lorsque l’opération d’envoi a été terminée (ignoré pour les sockets non exécutés).
Valeur retournée
Si aucune erreur ne se produit et que l’opération d’envoi s’est terminée immédiatement, WSASendTo 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 dans 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é correctement lancée 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é correctement lancée et qu’aucune indication d’achèvement ne se produira.
Code d'erreur | Signification |
---|---|
L’adresse demandée est une adresse de diffusion, mais l’indicateur approprié n’a pas été défini. | |
L’adresse distante n’est pas une adresse valide (par exemple, ADDR_ANY). | |
Impossible d'utiliser les adresses figurant dans la famille spécifiée avec ce socket. | |
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 ». | |
Une adresse de destination est requise. | |
Les paramètres lpBuffers, lpTo, lpOverlapped, lpNumberOfBytesSent ou lpCompletionRoutine ne font pas partie de l’espace d’adressage utilisateur, ou le paramètre lpTo est trop petit. | |
Une opération de socket a été tentée sur un hôte impossible à atteindre. | |
Un appel Windows Sockets 1.1 bloquant est en cours ou le fournisseur de services traite toujours une fonction de rappel. | |
Un appel Windows Socket 1.1 bloquant a été annulé via WSACancelBlockingCall. | |
Le socket n’a pas été lié à une liaison, ou le socket n’est pas créé avec l’indicateur qui se chevauche. | |
Le socket est orienté message, et le message est supérieur à la valeur maximale prise en charge par le transport sous-jacent. | |
Le sous-système réseau a échoué. | |
Pour un socket datagramme, cette erreur indique que la durée de vie (TTL, Time to Live) a expiré. | |
Le réseau ne peut pas être atteint à partir de cet hôte en ce moment. | |
Le fournisseur Windows Sockets signale un interblocage de mémoire tampon. | |
Le socket n’est pas connecté (sockets orientés connexion uniquement). | |
Le descripteur n’est pas un socket. | |
Le socket a été arrêté ; il n’est pas possible de WSASendTo sur un socket après l’appel de l’arrêt avec la valeur SD_SEND ou SD_BOTH. | |
Windows NT :
Sockets qui se chevauchent : il existe trop de demandes d’E/S superposées en attente. 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 superposée 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 ou de l’exécution de la commande SIO_FLUSH dans WSAIoctl. |
Remarques
La fonction WSASendTo fournit des fonctionnalités améliorées par rapport à la fonction sendto 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 les rend applicables au type d’E/S de nuages de points/regroupements.
Pour les sockets superposés (créés à l’aide de WSASocket avec indicateur WSA_FLAG_OVERLAPPED), l’envoi de données utilise des E/S superposées, sauf si lpOverlapped et lpCompletionRoutine sont tous deux NULL , auquel cas le socket est traité comme un socket non superposé. Une indication d’achèvement se produit (en appelant la routine d’achèvement ou le paramètre d’un objet é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.
Pour les sockets non inexploités, les deux derniers paramètres (lpOverlapped, lpCompletionRoutine) sont ignorés et WSASendTo 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 de transport. Si le socket est non bloquant et orienté flux, et qu’il n’y a pas suffisamment d’espace dans la mémoire tampon du transport, WSASendTo 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, WSASendTo se bloque jusqu’à ce que tout le contenu de la mémoire tampon de l’application ait été consommé.
Si cette fonction se chevauche, il incombe au fournisseur de services Winsock de capturer les structures WSABUF avant de revenir de cet appel. Cela permet aux applications de créer des tableaux WSABUF basés sur une pile pointés par le paramètre lpBuffers .
Pour les sockets orientés message, vous devez veiller à ne pas dépasser la taille maximale des messages du transport 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 atomiquement par le protocole sous-jacent, l’erreur WSAEMSGSIZE est retournée et aucune donnée n’est transmise.
Si le socket n’est pas lié, des valeurs uniques sont affectées à l’association locale par le système, et le socket est alors marqué comme lié.
Si le socket est connecté, la fonction getsockname peut être utilisée pour déterminer l’adresse IP locale et le port associés au socket.
Si le socket n’est pas connecté, le
La fonction getsockname peut être utilisée pour déterminer le numéro de port local associé au socket, mais l’adresse IP retournée est définie sur l’adresse générique pour le protocole donné (par exemple, INADDR_ANY ou « 0.0.0.0 » pour IPv4 et IN6ADDR_ANY_INIT ou « : : » pour IPv6).
La réussite d’un WSASendTo n’indique pas que les données ont été correctement livrées.
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 . Cette dernière est construite à 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 Socket peut choisir d’ignorer cet indicateur. |
MSG_OOB | Envoyer des données OOB (socket de type flux, comme SOCK_STREAM uniquement). |
MSG_PARTIAL | Spécifie que lpBuffers contient uniquement un message partiel. N’oubliez pas que le code d’erreur WSAEOPNOTSUPP sera retourné par des transports qui ne prennent pas en charge les transmissions partielles de messages. |
E/S de sockets qui se chevauchent
Si une opération qui se chevauche se termine immédiatement, WSASendTo retourne la valeur 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, WSASendTo 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 par le biais du 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 passe un lpCompletionRoutine non NULL et appelle ultérieurement WSAGetOverlappedResult pour la même demande d’E/S qui se chevauche peut ne 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 produirait des résultats imprévisibles.
La routine d’achèvement suit les mêmes règles que celles spécifié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 du socket et de garantir que, pour un socket donné, les routines d’achèvement d’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.
Le prototype de la routine d’achèvement est le suivant.
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. Le paramètre cbTransferred spécifie le nombre d’octets envoyés. Actuellement, aucune valeur d’indicateur n’est définie et dwFlags sera égal à zéro. Cette fonction ne retourne pas de valeur.
Le retour à partir de cette fonction permet d’appeler 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 d’exécution des opérations qui se chevauchent. Toutefois, il est garanti que les mémoires tampons publiées soient envoyées dans l’ordre spécifié.
Exemple de code
L’exemple suivant illustre l’utilisation de la fonction WSASendTo à l’aide d’un objet d’événement.#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
int __cdecl main(int argc, char **argv)
{
//---------------------------------------------
// Declare and initialize variables
WSADATA wsaData;
WSABUF DataBuf;
WSAOVERLAPPED Overlapped;
SOCKET SendToSocket = INVALID_SOCKET;
struct sockaddr_in RecvAddr;
struct sockaddr_in LocalAddr;
int RecvAddrSize = sizeof (RecvAddr);
int LocalAddrSize = sizeof (LocalAddr);
u_short Port = 27777;
struct hostent *localHost;
char *ip;
char *targetip;
char *targetport;
char SendBuf[1024] = "Data buffer to send";
int BufLen = 1024;
DWORD BytesSent = 0;
DWORD Flags = 0;
int rc, err;
int retval = 0;
// Validate the parameters
if (argc != 3) {
printf("usage: %s targetip port\n", argv[0]);
printf(" to sendto the localhost on port 27777\n");
printf(" %s 127.0.0.1 27777\n", argv[0]);
return 1;
}
targetip = argv[1];
targetport = argv[2];
//---------------------------------------------
// Initialize Winsock
// Load Winsock
rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (rc != 0) {
printf("Unable to load Winsock: %d\n", rc);
return 1;
}
// Make sure the Overlapped struct is zeroed out
SecureZeroMemory((PVOID) &Overlapped, sizeof(WSAOVERLAPPED));
// Create an event handle and setup the overlapped structure.
Overlapped.hEvent = WSACreateEvent();
if (Overlapped.hEvent == WSA_INVALID_EVENT) {
printf("WSACreateEvent failed with error: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
//---------------------------------------------
// Create a socket for sending data
SendToSocket =
WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0,
WSA_FLAG_OVERLAPPED);
if (SendToSocket == INVALID_SOCKET) {
printf("socket failed with error: %d\n", WSAGetLastError());
WSACloseEvent(Overlapped.hEvent);
WSACleanup();
return 1;
}
//---------------------------------------------
// Set up the RecvAddr structure with the IP address of
// the receiver (in this example case "123.123.123.1")
// and the specified port number.
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_addr.s_addr = inet_addr(targetip);
if (RecvAddr.sin_addr.s_addr == INADDR_NONE) {
printf("The target ip address entered must be a legal IPv4 address\n");
WSACloseEvent(Overlapped.hEvent);
WSACleanup();
return 1;
}
RecvAddr.sin_port = htons( (u_short) atoi(targetport));
if(RecvAddr.sin_port == 0) {
printf("The targetport must be a legal UDP port number\n");
WSACloseEvent(Overlapped.hEvent);
WSACleanup();
return 1;
}
//---------------------------------------------
// Set up the LocalAddr structure with the local IP address
// and the specified port number.
localHost = gethostbyname("");
ip = inet_ntoa(*(struct in_addr *) *localHost->h_addr_list);
LocalAddr.sin_family = AF_INET;
LocalAddr.sin_addr.s_addr = inet_addr(ip);
LocalAddr.sin_port = htons(Port);
//---------------------------------------------
// Bind the sending socket to the LocalAddr structure
// that has the internet address family, local IP address
// and specified port number.
rc = bind(SendToSocket, (struct sockaddr *) &LocalAddr, LocalAddrSize);
if (rc == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
WSACloseEvent(Overlapped.hEvent);
closesocket(SendToSocket);
WSACleanup();
return 1;
}
//---------------------------------------------
// Send a datagram to the receiver
printf("Sending datagram from IPv4 address = %s port=%d\n",
inet_ntoa(LocalAddr.sin_addr), ntohs(LocalAddr.sin_port) );
printf(" to IPv4 address = %s port=%d\n",
inet_ntoa(RecvAddr.sin_addr), ntohs(RecvAddr.sin_port) );
// printf("Sending a datagram...\n");
DataBuf.len = BufLen;
DataBuf.buf = SendBuf;
rc = WSASendTo(SendToSocket, &DataBuf, 1,
&BytesSent, Flags, (SOCKADDR *) & RecvAddr,
RecvAddrSize, &Overlapped, NULL);
if ((rc == SOCKET_ERROR) && (WSA_IO_PENDING != (err = WSAGetLastError()))) {
printf("WSASendTo failed with error: %d\n", err);
WSACloseEvent(Overlapped.hEvent);
closesocket(SendToSocket);
WSACleanup();
return 1;
}
rc = WSAWaitForMultipleEvents(1, &Overlapped.hEvent, TRUE, INFINITE, TRUE);
if (rc == WSA_WAIT_FAILED) {
printf("WSAWaitForMultipleEvents failed with error: %d\n",
WSAGetLastError());
retval = 1;
}
rc = WSAGetOverlappedResult(SendToSocket, &Overlapped, &BytesSent,
FALSE, &Flags);
if (rc == FALSE) {
printf("WSASendTo failed with error: %d\n", WSAGetLastError());
retval = 1;
}
else
printf("Number of sent bytes = %d\n", BytesSent);
//---------------------------------------------
// When the application is finished sending, close the socket.
printf("Finished sending. Closing socket.\n");
WSACloseEvent(Overlapped.hEvent);
closesocket(SendToSocket);
printf("Exiting.\n");
//---------------------------------------------
// Clean up and quit.
WSACleanup();
return (retval);
}
Windows Phone 8 : cette fonction est prise en charge pour les applications du Store Windows Phone 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 |