Funzione WSASendTo (winsock2.h)
La funzione WSASendTo invia dati a una destinazione specifica, usando le operazioni di I/O sovrapposte, se applicabile.
Sintassi
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
);
Parametri
[in] s
Descrittore che identifica un socket (possibilmente connesso).
[in] lpBuffers
Puntatore a una matrice di strutture WSABUF . Ogni struttura WSABUF contiene un puntatore a un buffer e la lunghezza del buffer, in byte. Per un'applicazione Winsock, una volta chiamata la funzione WSASendTo , 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 di byte inviati 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 WSASendTo .
[in] lpTo
Puntatore facoltativo all'indirizzo del socket di destinazione nella struttura SOCKADDR .
[in] iTolen
Dimensione, in byte, dell'indirizzo nel parametro lpTo .
[in] lpOverlapped
Puntatore a una struttura WSAOVERLAPPED (ignorata per i socket non sovrapposti).
[in] lpCompletionRoutine
Tipo: _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE
Puntatore alla routine di completamento chiamata quando l'operazione di invio è stata completata (ignorata per i socket non sovrapposti).
Valore restituito
Se non si verifica alcun errore e l'operazione di invio è stata completata immediatamente, WSASendTo 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 |
---|---|
L'indirizzo richiesto è un indirizzo broadcast, ma il flag appropriato non è stato impostato. | |
L'indirizzo remoto non è un indirizzo valido, ad esempio ADDR_ANY. | |
Impossibile utilizzare gli indirizzi della famiglia specificata con questo socket. | |
Per un socket datagram UDP, questo errore indica che un'operazione di invio precedente ha generato un messaggio ICMP "Port Unreachable". | |
È necessario un indirizzo di destinazione. | |
I parametri lpBuffers, lpTo, lpOverlapped, lpNumberOfBytesSent o lpCompletionRoutine non fanno parte dello spazio indirizzi utente o il parametro lpTo è troppo piccolo. | |
Tentativo di operazione del socket verso un host non raggiungibile. | |
È in corso una chiamata di Windows Sockets 1.1 bloccante oppure il provider di servizi sta ancora elaborando una funzione di callback. | |
Una chiamata di Windows Socket 1.1 bloccata è stata annullata tramite WSACancelBlockingCall. | |
Il socket non è stato associato con binding o il socket non viene creato con il flag sovrapposto. | |
Il socket è orientato ai messaggi e il messaggio è maggiore del massimo supportato dal trasporto sottostante. | |
Il sottosistema di rete non è riuscito. | |
Per un socket di datagramma, questo errore indica che la durata (TTL) è scaduta. | |
Impossibile raggiungere la rete da questo host in questo momento. | |
Il provider Windows Sockets segnala un deadlock del buffer. | |
Il socket non è connesso (solo socket orientati alla connessione). | |
Il descrittore non è un socket. | |
Il socket è stato arrestato; non è possibile WSASendTo in un socket dopo che è stato richiamato l'arresto con come impostare su SD_SEND o SD_BOTH. | |
Windows NT:
Socket sovrapposti: sono presenti troppe richieste di I/O sovrapposte in sospeso. Socket non sovrapposti: il socket è contrassegnato come non bloccante e l'operazione di invio non può essere completata immediatamente. |
|
Prima di usare questa funzione, è necessario che venga eseguita una chiamata WSAStartup riuscita. | |
Un'operazione sovrapposta è stata avviata correttamente e il completamento verrà indicato in un secondo momento. | |
L'operazione sovrapposta è stata annullata a causa della chiusura del socket o dell'esecuzione del comando SIO_FLUSH in WSAIoctl. |
Commenti
La funzione WSASendTo offre funzionalità avanzate sulla funzione sendto 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.
Per i socket sovrapposti (creati usando WSASocket con flag WSA_FLAG_OVERLAPPED) l'invio dei dati usa operazioni di I/O sovrapposte, a meno che sia lpOverlapped che lpCompletionRoutine siano NULL nel qual caso il socket viene considerato come un socket non sovrapposto. Si verificherà un'indicazione di completamento (richiamando la routine di completamento o l'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.
Per i socket non sovrapposti, gli ultimi due parametri (lpOverlapped, lpCompletionRoutine) vengono ignorati e WSASendTo adotta la stessa semantica di blocco dell'invio. I dati sono copiati dai buffer nel buffer di trasporto. Se il socket non blocca e orientato al flusso e non è disponibile spazio sufficiente nel buffer del trasporto, WSASendTo restituisce solo parte dei buffer dell'applicazione che sono stati utilizzati. Data la stessa situazione del buffer e un socket di blocco, WSASendTo verrà bloccato fino a quando non viene utilizzato tutto il contenuto del buffer dell'applicazione.
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, è necessario prestare attenzione a non superare le dimensioni massime del messaggio del trasporto 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.
Se il socket non è associato, i valori univoci vengono assegnati all'associazione locale dal sistema e il socket viene quindi contrassegnato come associato.
Se il socket è connesso, la funzione getsockname può essere usata per determinare l'indirizzo IP locale e la porta associati al socket.
Se il socket non è connesso,
La funzione getsockname può essere usata per determinare il numero di porta locale associato al socket, ma l'indirizzo IP restituito è impostato sull'indirizzo con caratteri jolly per il protocollo specificato( ad esempio, INADDR_ANY o "0.0.0.0" per IPv4 e IN6ADDR_ANY_INIT o "::" per IPv6).
Il completamento riuscito di un WSASendTo non indica che i dati sono stati recapitati correttamente.
Il parametro dwFlags può essere usato per influenzare il comportamento della chiamata alla 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 Socket può scegliere di ignorare questo flag. |
MSG_OOB | Inviare dati OOB (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. |
I/O del socket sovrapposto
Se un'operazione sovrapposta viene completata immediatamente, WSASendTo 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, WSASendTo 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.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.
Il prototipo della routine di completamento è il seguente.
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. Il parametro 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 in cui vengono completate le operazioni sovrapposte. Tuttavia, i buffer pubblicati devono essere inviati nello stesso ordine specificato.
Codice di esempio
Nell'esempio seguente viene illustrato l'uso della funzione WSASendTo usando un oggetto evento.#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: 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 |