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
WSAEACCES
L’adresse demandée est une adresse de diffusion, mais l’indicateur approprié n’a pas été défini.
WSAEADDRNOTAVAIL
L’adresse distante n’est pas une adresse valide (par exemple, ADDR_ANY).
WSAEAFNOSUPPORT
Impossible d'utiliser les adresses figurant dans la famille spécifiée avec ce socket.
WSAECONNRESET
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 ».
WSAEDESTADDRREQ
Une adresse de destination est requise.
WSAEFAULT
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.
WSAEHOSTUNREACH
Une opération de socket a été tentée sur un hôte impossible à atteindre.
WSAEINPROGRESS
Un appel Windows Sockets 1.1 bloquant est en cours ou le fournisseur de services traite toujours une fonction de rappel.
WSAEINTR
Un appel Windows Socket 1.1 bloquant a été annulé via WSACancelBlockingCall.
WSAEINVAL
Le socket n’a pas été lié à une liaison, ou le socket n’est pas créé avec l’indicateur qui se chevauche.
WSAEMSGSIZE
Le socket est orienté message, et le message est supérieur à la valeur maximale prise en charge par le transport sous-jacent.
WSAENETDOWN
Le sous-système réseau a échoué.
WSAENETRESET
Pour un socket datagramme, cette erreur indique que la durée de vie (TTL, Time to Live) a expiré.
WSAENETUNREACH
Le réseau ne peut pas être atteint à partir de cet hôte en ce moment.
WSAENOBUFS
Le fournisseur Windows Sockets signale un interblocage de mémoire tampon.
WSAENOTCONN
Le socket n’est pas connecté (sockets orientés connexion uniquement).
WSAENOTSOCK
Le descripteur n’est pas un socket.
WSAESHUTDOWN
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.
WSAEWOULDBLOCK
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.

WSANOTINITIALISED
Un appel WSAStartup réussi doit se produire avant d’utiliser cette fonction.
WSA_IO_PENDING
Une opération superposée a été lancée avec succès et l’achèvement sera indiqué ultérieurement.
WSA_OPERATION_ABORTED
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.
La fonction WSASendTo est normalement utilisée sur un socket sans connexion spécifié par s pour envoyer un datagramme contenu dans une ou plusieurs mémoires tampons à un socket homologue spécifique identifié par le paramètre lpTo . Même si le socket sans connexion a été précédemment connecté à l’aide de la fonction connect à une adresse spécifique, lpTo remplace l’adresse de destination pour ce datagramme particulier uniquement. Sur un socket orienté connexion, les paramètres lpTo et iToLen sont ignorés ; dans ce cas, WSASendTo équivaut à WSASend.

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.

Note Si un socket est ouvert, un appel setsockopt est effectué, puis un appel sendto est effectué, Windows Sockets effectue un appel de fonction de liaison implicite.
 
Si lpOverlapped et lpCompletionRoutine ont la valeur NULL, le socket dans cette fonction est traité comme un socket non inexploité.

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.
 
Note Lors de l’émission d’un appel Winsock bloquant tel que WSASendTo avec le paramètre lpOverlapped défini sur NULL, Winsock peut avoir besoin d’attendre qu’un événement réseau se termine. Winsock effectue une attente alertable dans cette situation, qui peut être interrompue par un appel de procédure asynchrone (APC) planifié sur le même thread. L’émission d’un autre appel Winsock bloquant à l’intérieur d’un APC qui a interrompu un appel Winsock bloquant en cours sur le même thread entraîne un comportement non défini et ne doit jamais être tenté par les clients Winsock.
 

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.
Note Toutes les E/S initiées par un thread donné sont annulées à la sortie de ce thread. Pour les sockets qui se chevauchent, les opérations asynchrones en attente peuvent échouer si le thread est fermé avant la fin des opérations. Pour plus d’informations, consultez ExitThread .
 
La fonction WSASendTo à l’aide d’E/S superposées peut être appelée à partir de la routine d’achèvement d’une fonction WSARecv, WSARecvFrom, WSASend ou WSASendTo précédente. Cela permet aux transmissions de données sensibles au temps de se produire entièrement dans un contexte préemptif.

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

Voir aussi

WSACloseEvent

WSACreateEvent

WSAGetOverlappedResult

WSASocket

WSAWaitForMultipleEvents

Fonctions Winsock

Informations de référence sur Winsock