Condividi tramite


Funzione WSASend (winsock2.h)

La funzione WSASend invia dati su un socket connesso.

Sintassi

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
);

Parametri

[in] s

Descrittore che identifica un socket connesso.

[in] lpBuffers

Puntatore a una matrice di strutture WSABUF . Ogni struttura WSABUF contiene un puntatore a un buffer e la lunghezza, in byte, del buffer. Per un'applicazione Winsock, una volta chiamata la funzione WSASend , il sistema possiede questi buffer e l'applicazione potrebbe non accedervi. Questa matrice deve rimanere valida per la durata dell'operazione di invio.

[in] dwBufferCount

Numero di strutture WSABUF nella matrice lpBuffers .

[out] lpNumberOfBytesSent

Puntatore al numero, in byte, inviato da questa chiamata se l'operazione di I/O viene completata immediatamente.

Usare NULL per questo parametro se il parametro lpOverlapped non è NULL per evitare risultati potenzialmente errati. Questo parametro può essere NULL solo se il parametro lpOverlapped non è NULL.

[in] dwFlags

Flag utilizzati per modificare il comportamento della chiamata di funzione WSASend . Per altre informazioni, vedere Uso di dwFlags nella sezione Osservazioni.

[in] lpOverlapped

Puntatore a una struttura WSAOVERLAPPED . Questo parametro viene ignorato per i socket non sovrapposti.

[in] lpCompletionRoutine

Tipo: _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE

Puntatore alla routine di completamento chiamata al completamento dell'operazione di invio. Questo parametro viene ignorato per i socket non sovrapposti.

Valore restituito

Se non si verifica alcun errore e l'operazione di invio è stata completata immediatamente, WSASend restituisce zero. In questo caso, la routine di completamento sarà già stata pianificata per essere chiamata dopo che il thread chiamante si trova nello stato di avviso. In caso contrario, viene restituito un valore di SOCKET_ERROR e è possibile recuperare un codice di errore specifico chiamando WSAGetLastError. Il codice di errore WSA_IO_PENDING indica che l'operazione sovrapposta è stata avviata correttamente e che il completamento verrà indicato in un secondo momento. Qualsiasi altro codice di errore indica che l'operazione sovrapposta non è stata avviata correttamente e non si verificherà alcuna indicazione di completamento.

Codice di errore Significato
WSAECONNABORTED
Circuito virtuale terminato a causa di un timeout o di un altro errore.
WSAECONNRESET
Per un socket di flusso, il circuito virtuale è stato reimpostato dal lato remoto. L'applicazione deve chiudere il socket che non è più utilizzabile. Per un socket datagram UDP, questo errore indica che un'operazione di invio precedente ha generato un messaggio ICMP "Port Unreachable".
WSAEFAULT
Il parametro lpBuffers, lpNumberOfBytesSent, lpOverlapped, lpCompletionRoutine non è totalmente contenuto in una parte valida dello spazio indirizzi utente.
WSAEINTR
Una chiamata di Windows Socket 1.1 bloccata è stata annullata tramite WSACancelBlockingCall.
WSAEINPROGRESS
È in corso una chiamata di Windows Sockets 1.1 bloccante oppure il provider di servizi sta ancora elaborando una funzione di callback.
WSAEINVAL
Il socket non è stato associato con binding o il socket non viene creato con il flag sovrapposto.
WSAEMSGSIZE
Il socket è orientato ai messaggi e il messaggio è maggiore del massimo supportato dal trasporto sottostante.
WSAENETDOWN
Il sottosistema di rete non è riuscito.
WSAENETRESET
Per un socket di flusso, la connessione è stata interrotta a causa dell'attività keep-alive che rileva un errore durante l'operazione in corso. Per un socket di datagramma, questo errore indica che la durata (TTL) è scaduta.
WSAENOBUFS
Il provider Windows Sockets segnala un deadlock del buffer.
WSAENOTCONN
Il socket non è connesso.
WSAENOTSOCK
Il descrittore non è un socket.
WSAEOPNOTSUPP
MSG_OOB è stato specificato, ma il socket non è in stile flusso, ad esempio il tipo SOCK_STREAM, i dati OOB non sono supportati nel dominio di comunicazione associato a questo socket, MSG_PARTIAL non è supportato o il socket è unidirezionale e supporta solo le operazioni di ricezione.
WSAESHUTDOWN
Il socket è stato arrestato; non è possibile eseguire WSASend su un socket dopo che è stato richiamato l'arresto con come impostare su SD_SEND o SD_BOTH.
WSAEWOULDBLOCK
Windows NT:

Socket sovrapposti: troppe richieste di I/O in sospeso in sospeso. Socket non sovrapposti: il socket è contrassegnato come non bloccante e l'operazione di invio non può essere completata immediatamente.

WSANOTINITIALISED
Prima di usare questa funzione, è necessario che venga eseguita una chiamata WSAStartup riuscita.
WSA_IO_PENDING
Un'operazione sovrapposta è stata avviata correttamente e il completamento verrà indicato in un secondo momento.
WSA_OPERATION_ABORTED
L'operazione sovrapposta è stata annullata a causa della chiusura del socket, dell'esecuzione del comando "SIO_FLUSH" in WSAIoctl o del thread che ha avviato la richiesta sovrapposta è stata chiusa prima del completamento dell'operazione. Per altre informazioni, vedere la sezione Osservazioni.

Commenti

La funzione WSASend fornisce funzionalità oltre e sopra la funzione di trasmissione standard in due aree importanti:

  • Può essere usato in combinazione con socket sovrapposti per eseguire operazioni di invio sovrapposte.
  • Consente di specificare più buffer di invio , rendendoli applicabili al tipo di I/O a dispersione/raccolta.
La funzione WSASend viene usata per scrivere dati in uscita da uno o più buffer in un socket orientato alla connessione specificato da s. Può essere usato anche nei socket senza connessione con un indirizzo peer predefinito stabilito tramite la funzione connect o WSAConnect .

Un socket creato dalla funzione socket avrà l'attributo sovrapposto come predefinito. Un socket creato dalla funzione WSASocket con il parametro dwFlags passato a WSASocket con il set di bit WSA_FLAG_OVERLAPPED avrà l'attributo sovrapposto. Per i socket con l'attributo sovrapposto, WSASend usa operazioni di I/O sovrapposte, a meno che i parametri lpOverlapped e lpCompletionRoutine non siano NULL. In tal caso, il socket viene considerato come un socket non sovrapposto. Si verificherà un'indicazione di completamento, richiamando il completamento di una routine o di un'impostazione di un oggetto evento, quando i buffer sono stati utilizzati dal trasporto. Se l'operazione non viene completata immediatamente, lo stato di completamento finale viene recuperato tramite la routine di completamento o WSAGetOverlappedResult.

Se sia lpOverlapped che lpCompletionRoutine sono NULL, il socket in questa funzione verrà considerato come un socket non sovrapposto.

Per i socket non sovrapposti, gli ultimi due parametri (lpOverlapped, lpCompletionRoutine) vengono ignorati e WSASend adotta la stessa semantica di blocco dell'invio. I dati sono copiati dai buffer nel buffer del trasporto. Se il socket non è bloccato e orientato al flusso e non è disponibile spazio sufficiente nel buffer del trasporto, WSASend restituirà solo parte dei buffer dell'applicazione che sono stati utilizzati. Data la stessa situazione del buffer e un socket di blocco, WSASend bloccherà fino a quando non saranno stati utilizzati tutti i contenuti del buffer dell'applicazione.

Nota Le opzioni socket SO_RCVTIMEO e SO_SNDTIMEO si applicano solo ai socket di blocco.
 
Se questa funzione viene completata in modo sovrapposto, è responsabilità del provider di servizi Winsock acquisire le strutture WSABUF prima di restituire da questa chiamata. Ciò consente alle applicazioni di compilare matrici WSABUF basate su stack a cui punta il parametro lpBuffers .

Per i socket orientati ai messaggi, non superare le dimensioni massime del messaggio del provider sottostante, che può essere ottenuto ottenendo il valore dell'opzione socket SO_MAX_MSG_SIZE. Se i dati sono troppo lunghi per passare atomicamente tramite il protocollo sottostante, viene restituito l'errore WSAEMSGSIZE e non vengono trasmessi dati.

Windows Me/98/95: La funzione WSASend non supporta più di 16 buffer.

Nota Il completamento corretto di un WSASend non indica che i dati sono stati recapitati correttamente.
 

Uso di dwFlags

Il parametro dwFlags può essere usato per influenzare il comportamento della chiamata di funzione oltre le opzioni specificate per il socket associato. Vale a dire, la semantica di questa funzione è determinata dalle opzioni socket e dal parametro dwFlags . Quest'ultimo viene costruito usando l'operatore OR bit per bit con uno qualsiasi dei valori elencati nella tabella seguente.
Valore Significato
MSG_DONTROUTE Specifica che i dati non devono essere soggetti al routing. Un provider di servizi Windows Sockets può scegliere di ignorare questo flag.
MSG_OOB Inviare dati OOB in un socket in stile flusso, ad esempio SOCK_STREAM solo.
MSG_PARTIAL Specifica che lpBuffers contiene solo un messaggio parziale. Tenere presente che il codice di errore WSAEOPNOTSUPP verrà restituito dai trasporti che non supportano le trasmissioni di messaggi parziali.
 
Nota Quando si emette una chiamata Winsock di blocco, ad esempio WSASend con il parametro lpOverlapped impostato su NULL, Winsock potrebbe dover attendere il completamento di un evento di rete. Winsock esegue un'attesa avvisabile in questa situazione, che può essere interrotta da una chiamata di routine asincrona pianificata nello stesso thread. L'emissione di un'altra chiamata winsock bloccata all'interno di un APC che ha interrotto una chiamata winsock in corso sullo stesso thread comporterà un comportamento non definito e non deve mai essere tentato dai client Winsock.
 

I/O del socket sovrapposto

Se un'operazione sovrapposta viene completata immediatamente, WSASend restituisce un valore pari a zero e il parametro lpNumberOfBytesSent viene aggiornato con il numero di byte inviati. Se l'operazione sovrapposta viene avviata correttamente e verrà completata in un secondo momento, WSASend restituisce SOCKET_ERROR e indica il codice di errore WSA_IO_PENDING. In questo caso, lpNumberOfBytesSent non viene aggiornato. Quando l'operazione sovrapposta completa la quantità di dati trasferiti viene indicato tramite il parametro cbTransferred nella routine di completamento (se specificato) o tramite il parametro lpcbTransfer in WSAGetOverlappedResult.
Nota Tutti gli I/O avviati da un determinato thread vengono annullati quando il thread viene chiuso. Per i socket sovrapposti, le operazioni asincrone in sospeso possono non riuscire se il thread viene chiuso prima del completamento delle operazioni. Per altre informazioni, vedere ExitThread.
 
La funzione WSASend con I/O sovrapposta può essere chiamata dalla routine di completamento di una funzione WSARecv precedente, WSARecvFrom, WSASend o WSASendTo. Ciò consente alle trasmissioni di dati sensibili al tempo di verificarsi interamente all'interno di un contesto preemptive.

Il parametro lpOverlapped deve essere valido per la durata dell'operazione sovrapposta. Se più operazioni di I/O sono in sospeso contemporaneamente, ognuna deve fare riferimento a una struttura WSAOVERLAPPED separata.

Se il parametro lpCompletionRoutine è NULL, il parametro hEvent di lpOverlapped viene segnalato quando l'operazione sovrapposta viene completata se contiene un handle di oggetto evento valido. Un'applicazione può usare WSAWaitForMultipleEvents o WSAGetOverlappedResult per attendere o eseguire il polling nell'oggetto evento.

Se lpCompletionRoutine non è NULL, il parametro hEvent viene ignorato e può essere usato dall'applicazione per passare le informazioni di contesto alla routine di completamento. Un chiamante che passa una richiesta non NULLlpCompletionRoutine e versioni successive chiama WSAGetOverlappedResult per la stessa richiesta di I/O sovrapposta potrebbe non impostare il parametro fWait per tale chiamata di WSAGetOverlappedResult su TRUE. In questo caso l'utilizzo del parametro hEvent non è definito e il tentativo di attendere il parametro hEvent genera risultati imprevedibili.

La routine di completamento segue le stesse regole previste per le routine di completamento di I/O file di Windows. La routine di completamento non verrà richiamata finché il thread non si trova in uno stato di attesa avvisabile, ad esempio quando viene richiamata la funzione WSAWaitForMultipleEvents con il parametro fAlertable impostato su TRUE .

I provider di trasporto consentono a un'applicazione di richiamare operazioni di invio e ricezione dall'interno del contesto della routine di completamento di I/O socket e garantire che, per un determinato socket, le routine di completamento di I/O non verranno annidate. In questo modo, le trasmissioni di dati sensibili al tempo vengono eseguite interamente all'interno di un contesto preemptive.

L'esempio di codice C++ seguente è un prototipo della routine di completamento.


void CALLBACK CompletionROUTINE(
  IN DWORD dwError,
  IN DWORD cbTransferred,
  IN LPWSAOVERLAPPED lpOverlapped,
  IN DWORD dwFlags
);

La funzione CompletionRoutine è un segnaposto per un nome di funzione definito dall'applicazione o dalla libreria. Il parametro dwError specifica lo stato di completamento dell'operazione sovrapposta, come indicato da lpOverlapped. cbTransferred specifica il numero di byte inviati. Attualmente non sono presenti valori di flag definiti e dwFlags saranno zero. Questa funzione non restituisce un valore.

La restituzione da questa funzione consente la chiamata di un'altra routine di completamento in sospeso per questo socket. Tutte le routine di completamento in attesa vengono chiamate prima che l'attesa del thread avvisabile sia soddisfatta con un codice restituito di WSA_IO_COMPLETION. Le routine di completamento possono essere chiamate in qualsiasi ordine, non necessariamente nello stesso ordine le operazioni sovrapposte vengono completate. Tuttavia, i buffer pubblicati devono essere inviati nello stesso ordine specificato.

L'ordine delle chiamate effettuate a WSASend è anche l'ordine in cui i buffer vengono trasmessi al livello di trasporto. WSASend non deve essere chiamato nello stesso socket orientato al flusso simultaneamente da thread diversi, perché alcuni provider Winsock possono suddividere una richiesta di invio di grandi dimensioni in più trasmissioni e questo può causare l'interleving dei dati non intenzionali da più richieste di invio simultanee nello stesso socket orientato al flusso.

Codice di esempio

Nell'esempio di codice seguente viene illustrato come usare la funzione WSASend in modalità I/O sovrapposta.
#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: questa funzione è supportata per le app Windows Phone Store in Windows Phone 8 e versioni successive.

Windows 8.1 e Windows Server 2012 R2: questa funzione è supportata per le app di Windows Store in Windows 8.1, Windows Server 2012 R2 e versioni successive.

Requisiti

Requisito Valore
Client minimo supportato Windows 8.1, Windows Vista [app desktop | App UWP]
Server minimo supportato Windows Server 2003 [app desktop | App UWP]
Piattaforma di destinazione Windows
Intestazione winsock2.h
Libreria Ws2_32.lib
DLL Ws2_32.dll

Vedi anche

WSABUF

WSACloseEvent

WSAConnect

WSACreateEvent

WSAGetOverlappedResult

WSAOVERLAPPED

WSASocket

WSAWaitForMultipleEvents

Funzioni Winsock

Informazioni di riferimento su Winsock

connect

send

socket