Funzione WSARecvFrom (winsock2.h)
La funzione WSARecvFrom riceve un datagram e archivia l'indirizzo di origine.
Sintassi
int WSAAPI WSARecvFrom(
[in] SOCKET s,
[in, out] LPWSABUF lpBuffers,
[in] DWORD dwBufferCount,
[out] LPDWORD lpNumberOfBytesRecvd,
[in, out] LPDWORD lpFlags,
[out] sockaddr *lpFrom,
[in, out] LPINT lpFromlen,
[in] LPWSAOVERLAPPED lpOverlapped,
[in] LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
Parametri
[in] s
Descrittore che identifica un socket.
[in, out] lpBuffers
Puntatore a una matrice di strutture WSABUF . Ogni struttura WSABUF contiene un puntatore a un buffer e la lunghezza del buffer.
[in] dwBufferCount
Numero di strutture WSABUF nella matrice lpBuffers .
[out] lpNumberOfBytesRecvd
Puntatore al numero di byte ricevuti da questa chiamata se l'operazione WSARecvFrom 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, out] lpFlags
Puntatore ai flag usati per modificare il comportamento della chiamata di funzione WSARecvFrom . Vedere la sezione Note riportata di seguito.
[out] lpFrom
Puntatore facoltativo a un buffer che conterrà l'indirizzo di origine al completamento dell'operazione sovrapposta.
[in, out] lpFromlen
Puntatore alle dimensioni, in byte, del buffer "from" richiesto solo se lpFrom è specificato.
[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 WSARecvFrom è stata completata (ignorata per i socket non sovrapposti).
Valore restituito
Se non si verifica alcun errore e l'operazione di ricezione è stata completata immediatamente, WSARecvFrom restituisce zero. In questo caso, la routine di completamento sarà già stata pianificata per essere chiamata una volta che il thread chiamante si trova nello stato avvisabile. In caso contrario, viene restituito un valore di SOCKET_ERROR e un codice di errore specifico può essere recuperato 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 |
---|---|
Circuito virtuale reimpostato dal lato remoto durante l'esecuzione di una chiusura definitiva o anomala. L'applicazione deve chiudere il socket che non è più utilizzabile. Per un socket di datagrammi UPD, questo errore indica che un'operazione di invio precedente ha generato un messaggio ICMP "Port Unreachable". | |
Il parametro lpBuffers, lpFlags, lpFrom, lpNumberOfBytesRecvd, lpFromlen, lpOverlapped o lpCompletionRoutine non è totalmente contenuto in una parte valida dello spazio indirizzi utente: il buffer lpFrom era troppo piccolo per ospitare l'indirizzo peer. | |
Una chiamata windows Sockets 1.1 bloccata è in corso 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 (ad esempio con binding). | |
Il messaggio era troppo grande per il buffer specificato e (solo per protocolli non affidabili) qualsiasi parte finale del messaggio che non è stata adattata al buffer. | |
Il sottosistema di rete non è riuscito. | |
Per un socket di datagramma, questo errore indica che la durata (TTL) è scaduta. | |
Il socket non è connesso (solo socket orientati alla connessione). | |
Windows NT:
Socket sovrapposti: sono presenti troppe richieste di I/O in sospeso. Socket non sovrapposti: il socket è contrassegnato come non sbloccante e l'operazione di ricezione non può essere completata immediatamente. |
|
Prima di usare questa funzione, è necessario eseguire 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. |
Commenti
La funzione WSARecvFrom offre funzionalità oltre e superiori alla funzione recvfrom standard in tre aree importanti:
- Può essere usato in combinazione con socket sovrapposti per eseguire operazioni di ricezione sovrapposte.
- Consente di specificare più buffer di ricezione che lo rendono applicabile al tipo di I/O a dispersione/raccolta.
- Il parametro lpFlags è sia un input che un parametro di output, consentendo alle applicazioni di percepire lo stato di output del flag MSG_PARTIAL . Tenere presente che il bit MSG_PARTIAL flag non è supportato da tutti i protocolli.
Per i socket sovrapposti, questa funzione viene usata per pubblicare uno o più buffer in cui verranno inseriti i dati in ingresso in quanto diventa disponibile in un socket (possibilmente connesso), dopo il quale si verifica l'indicazione di completamento specificata dall'applicazione (chiamata della routine di completamento o dell'impostazione di un oggetto evento). Se l'operazione non viene completata immediatamente, lo stato di completamento finale viene recuperato tramite la routine di completamento o WSAGetOverlappedResult. Inoltre, i valori indicati da lpFrom e lpFromlen non vengono aggiornati fino a quando il completamento non è indicato. Le applicazioni non devono usare o disturbare questi valori fino a quando non sono stati aggiornati; pertanto l'applicazione non deve usare le variabili automatiche (ovvero basate su stack) per questi parametri.
Per i socket non sovrapposti, la semantica di blocco è identica a quella della funzione WSARecv standard e i parametri lpOverlapped e lpCompletionRoutine vengono ignorati. Tutti i dati già ricevuti e memorizzati nel buffer dal trasporto verranno copiati nei buffer utente. Per il caso di un socket di blocco senza dati attualmente ricevuti e memorizzati nel buffer dal trasporto, la chiamata bloccherà fino alla ricezione dei dati.
I buffer vengono compilati nell'ordine in cui vengono visualizzati nella matrice indicata da lpBuffers e i buffer vengono compressi in modo che non vengano creati fori.
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 creare matrici WSABUF basate su stack puntate dal parametro lpBuffers .
Per i tipi di socket senza connessione, l'indirizzo da cui provengono i dati viene copiato nel buffer indicato da lpFrom. Il valore indicato da lpFromlen viene inizializzato per le dimensioni di questo buffer e viene modificato al completamento per indicare la dimensione effettiva dell'indirizzo archiviato. Come indicato in precedenza per i socket sovrapposti, i parametri lpFrom e lpFromlen non vengono aggiornati fino al completamento dell'I/O sovrapposto. La memoria puntata da questi parametri deve pertanto rimanere disponibile per il provider di servizi e non può essere allocata nel frame dello stack di applicazioni. I parametri lpFrom e lpFromlen vengono ignorati per i socket orientati alla connessione.
Per i socket in stile di flusso di byte (ad esempio, digitare SOCK_STREAM), i dati in ingresso vengono inseriti nei buffer fino a quando:
- I buffer vengono riempiti.
- La connessione è chiusa.
- I dati memorizzati nel buffer interno vengono esauriti.
Il parametro lpFlags 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 lpFlags . Quest'ultimo viene costruito usando l'operatore OR bit per bit con uno qualsiasi dei valori elencati nella tabella seguente.
Valore | Significato |
---|---|
MSG_PEEK | Visualizza in anteprima i dati in ingresso. I dati vengono copiati nel buffer, ma non vengono rimossi dalla coda di input. Questo flag è valido solo per i socket non sovrapposti. |
MSG_OOB | Elabora i dati OOB. |
MSG_PARTIAL | Questo flag è solo per socket orientati ai messaggi. Nell'output, questo flag indica che i dati sono una parte del messaggio trasmesso dal mittente. Le parti rimanenti del messaggio verranno trasmesse nelle operazioni di ricezione successive. Un'operazione di ricezione successiva con flag MSG_PARTIAL deselezionata indica la fine del messaggio del mittente.
Come parametro di input, questo flag indica che l'operazione di ricezione deve essere completata anche se è stata ricevuta solo parte di un messaggio dal provider di servizi. |
Per i socket orientati ai messaggi, il bit di MSG_PARTIAL viene impostato nel parametro lpFlags se viene ricevuto un messaggio parziale. Se viene ricevuto un messaggio completo, MSG_PARTIAL viene cancellato in lpFlags. Nel caso di completamento ritardato, il valore puntato da lpFlags non viene aggiornato. Quando il completamento è stato indicato che l'applicazione deve chiamare WSAGetOverlappedResult ed esaminare i flag a cui punta il parametro lpdwFlags .
I/O del socket sovrapposto
Se un'operazione sovrapposta viene completata immediatamente, WSARecvFrom restituisce un valore pari a zero e il parametro lpNumberOfBytesRecvd viene aggiornato con il numero di byte ricevuti e i bit di flag puntati dal parametro lpFlags vengono aggiornati anche. Se l'operazione sovrapposta viene avviata correttamente e verrà completata in un secondo momento, WSARecvFrom restituisce SOCKET_ERROR e indica il codice di errore WSA_IO_PENDING. In questo caso, lpNumberOfBytesRecvd e lpFlags 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. I valori del flag vengono ottenuti tramite il parametro dwFlags della routine di completamento oppure esaminando il parametro lpdwFlags di WSAGetOverlappedResult.La funzione WSARecvFrom può essere chiamata dall'interno della routine di completamento di una funzione WSARecv, WSARecvFrom, WSASend o WSASendTo. 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 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 .
Se viene usata una porta di completamento I/O e il parametro lpCompletionRoutine e il parametro hEvent sono NULL, il risultato dell'operazione è pianificato sulla porta di completamento di I/O. Ciò avviene per tutte le operazioni riuscite, indipendentemente dal fatto che le operazioni vengano completate immediatamente o meno.
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
);
CompletamentoRoutine è un segnaposto per un nome di funzione definito dall'applicazione o dalla libreria. DwError specifica lo stato di completamento per l'operazione sovrapposta, come indicato da lpOverlapped. CbTransferred specifica il numero di byte ricevuti. Il parametro dwFlags contiene informazioni che sarebbero state visualizzate in lpFlags se l'operazione di ricezione era stata completata immediatamente. 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. Quando si usa WSAWaitForMultipleEvents, tutte le routine di completamento in attesa vengono chiamate prima che l'attesa del thread avvisabile venga 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 sono garantiti di essere compilati nello stesso ordine specificato.
Codice di esempio
Nell'esempio seguente viene illustrato l'uso della funzione WSARecvFrom .#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>
int __cdecl main()
{
WSADATA wsaData;
WSABUF DataBuf;
WSAOVERLAPPED Overlapped;
SOCKET RecvSocket = INVALID_SOCKET;
struct sockaddr_in RecvAddr;
struct sockaddr_in SenderAddr;
int SenderAddrSize = sizeof (SenderAddr);
u_short Port = 27015;
char RecvBuf[1024];
int BufLen = 1024;
DWORD BytesRecv = 0;
DWORD Flags = 0;
int err = 0;
int rc;
int retval = 0;
//-----------------------------------------------
// Initialize Winsock
rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (rc != 0) {
/* Could not find a usable Winsock DLL */
wprintf(L"WSAStartup failed with error: %ld\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 == NULL) {
wprintf(L"WSACreateEvent failed with error: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
//-----------------------------------------------
// Create a receiver socket to receive datagrams
RecvSocket = WSASocket(AF_INET,
SOCK_DGRAM,
IPPROTO_UDP, NULL, 0, WSA_FLAG_OVERLAPPED);
if (RecvSocket == INVALID_SOCKET) {
/* Could not open a socket */
wprintf(L"WSASocket failed with error: %ld\n", WSAGetLastError());
WSACloseEvent(Overlapped.hEvent);
WSACleanup();
return 1;
}
//-----------------------------------------------
// Bind the socket to any address and the specified port.
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
rc = bind(RecvSocket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));
if (rc != 0) {
/* Bind to the socket failed */
wprintf(L"bind failed with error: %ld\n", WSAGetLastError());
WSACloseEvent(Overlapped.hEvent);
closesocket(RecvSocket);
WSACleanup();
return 1;
}
//-----------------------------------------------
// Call the recvfrom function to receive datagrams
// on the bound socket.
DataBuf.len = BufLen;
DataBuf.buf = RecvBuf;
wprintf(L"Listening for incoming datagrams on port=%d\n", Port);
rc = WSARecvFrom(RecvSocket,
&DataBuf,
1,
&BytesRecv,
&Flags,
(SOCKADDR *) & SenderAddr,
&SenderAddrSize, &Overlapped, NULL);
if (rc != 0) {
err = WSAGetLastError();
if (err != WSA_IO_PENDING) {
wprintf(L"WSARecvFrom failed with error: %ld\n", err);
WSACloseEvent(Overlapped.hEvent);
closesocket(RecvSocket);
WSACleanup();
return 1;
}
else {
rc = WSAWaitForMultipleEvents(1, &Overlapped.hEvent, TRUE, INFINITE, TRUE);
if (rc == WSA_WAIT_FAILED) {
wprintf(L"WSAWaitForMultipleEvents failed with error: %d\n", WSAGetLastError());
retval = 1;
}
rc = WSAGetOverlappedResult(RecvSocket, &Overlapped, &BytesRecv,
FALSE, &Flags);
if (rc == FALSE) {
wprintf(L"WSArecvFrom failed with error: %d\n", WSAGetLastError());
retval = 1;
}
else
wprintf(L"Number of received bytes = %d\n", BytesRecv);
wprintf(L"Finished receiving. Closing socket.\n");
}
}
//---------------------------------------------
// When the application is finished receiving, close the socket.
WSACloseEvent(Overlapped.hEvent);
closesocket(RecvSocket);
wprintf(L"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
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 |