Partager via


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
WSAECONNABORTED
Le circuit virtuel a été interrompu en raison d'un délai d'attente ou d'un autre échec.
WSAECONNRESET
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 ».
WSAEFAULT
Le paramètre lpBuffers, lpNumberOfBytesSent, lpOverlapped, lpCompletionRoutine n’est pas totalement contenu dans une partie valide de l’espace d’adressage utilisateur.
WSAEINTR
Un appel bloquant Windows Socket 1.1 a été annulé via WSACancelBlockingCall.
WSAEINPROGRESS
Un appel bloquant Windows Sockets 1.1 est en cours ou le fournisseur de services traite toujours une fonction de rappel.
WSAEINVAL
Le socket n’a pas été lié à bind ou le socket n’est pas créé avec l’indicateur qui se chevauche.
WSAEMSGSIZE
Le socket est orienté message et le message est plus grand que le maximum pris en charge par le transport sous-jacent.
WSAENETDOWN
Le sous-système réseau a échoué.
WSAENETRESET
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é.
WSAENOBUFS
Le fournisseur Windows Sockets signale un interblocage de mémoire tampon.
WSAENOTCONN
Le socket n'est pas connecté.
WSAENOTSOCK
Le descripteur n’est pas un socket.
WSAEOPNOTSUPP
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.
WSAESHUTDOWN
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.
WSAEWOULDBLOCK
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.

WSANOTINITIALISED
Un appel WSAStartup réussi doit se produire avant d’utiliser cette fonction.
WSA_IO_PENDING
Une opération qui se chevauche 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, 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.
La fonction WSASend est utilisée pour écrire des données sortantes à partir d’un ou plusieurs tampons sur un socket orienté connexion spécifié par s. Il peut également être utilisé, toutefois, sur les sockets sans connexion qui ont une adresse d’homologue par défaut spécifiée établie par le biais de la fonction connect ou WSAConnect .

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é.

Note Les options de socket SO_RCVTIMEO et SO_SNDTIMEO s’appliquent uniquement aux sockets bloquants.
 
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, 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.

Note La réussite d’un WSASend n’indique pas que les données ont été correctement livrées.
 

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.
 
Note Lors de l’émission d’un appel Winsock bloquant tel que WSASend avec le paramètre lpOverlapped défini sur NULL, Winsock peut avoir besoin d’attendre un événement réseau avant la fin de l’appel. Winsock effectue une attente pouvant être alertée 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 interrompt 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 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.
Note Toutes les E/S initiées par un thread donné sont annulées lorsque ce thread se ferme. 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 WSASend à 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 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

Voir aussi

WSABUF

WSACloseEvent

WSAConnect

WSACreateEvent

WSAGetOverlappedResult

WSAOVERLAPPED

WSASocket

WSAWaitForMultipleEvents

Winsock Functions

Référence Winsock

connect

envoyer

socket