Funzione di callback LPWSPRECV (ws2spi.h)
La funzione LPWSPRecv riceve i dati in un socket.
Sintassi
LPWSPRECV Lpwsprecv;
int Lpwsprecv(
[in] SOCKET s,
\[in\, out\] LPWSABUF lpBuffers,
[in] DWORD dwBufferCount,
[out] LPDWORD lpNumberOfBytesRecvd,
\[in\, out\] LPDWORD lpFlags,
[in] LPWSAOVERLAPPED lpOverlapped,
[in] LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
[in] LPWSATHREADID lpThreadId,
[out] LPINT lpErrno
)
{...}
Parametri
[in] s
Descrittore che identifica un socket connesso.
\\[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 byte.
[in] dwBufferCount
Numero di strutture WSABUF nella matrice lpBuffers .
[out] lpNumberOfBytesRecvd
Puntatore al numero di byte ricevuti da questa chiamata.
\\[in\\, out\\] lpFlags
Puntatore ai flag che specificano il modo in cui viene effettuata la chiamata.
[in] lpOverlapped
Puntatore a una struttura WSAOverlapped (ignorata per strutture non sovrapposte).
[in] lpCompletionRoutine
Tipo: _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE
Puntatore alla routine di completamento chiamata quando l'operazione di ricezione è stata completata (ignorata per strutture non sovrapposte).
[in] lpThreadId
Puntatore a una struttura WSATHREADID da usare dal provider in una chiamata successiva a WPUQueueApc. Il provider deve archiviare la struttura WSATHREADID a cui fa riferimento (non lo stesso puntatore) fino a quando la funzione WPUQueueApc restituisce.
[out] lpErrno
Puntatore al codice di errore.
Valore restituito
Se non si verifica alcun errore e l'operazione di ricezione è stata completata immediatamente, LPWSPRecv restituisce zero. Si noti che in questo caso la routine di completamento, se specificata, sarà già stata accodata. In caso contrario, viene restituito un valore di SOCKET_ERROR e un codice di errore specifico è disponibile in lpErrno. 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 non è stata avviata alcuna operazione sovrapposta e non si verificherà alcuna indicazione di completamento.
Codice di errore | Significato |
---|---|
Il sottosistema di rete non è riuscito. | |
Socket non connesso. | |
(Blocco) chiamata annullata tramite LPWSPCancelBlockingCall. | |
Il blocco della chiamata a Windows Sockets è in corso oppure il provider di servizi sta ancora elaborando una funzione di callback. | |
La connessione è stata interrotta a causa dell'attività keep-alive che rileva un errore durante l'operazione in corso. | |
Il parametro lpBuffers non è totalmente contenuto in una parte valida dello spazio degli indirizzi utente. | |
Il descrittore non è un socket. | |
MSG_OOB è stato specificato, ma il socket non è in stile di flusso, ad esempio il tipo SOCK_STREAM, i dati OOB non sono supportati nel dominio di comunicazione associato a questo socket o il socket è unidirectional e supporta solo le operazioni di invio. | |
Il socket è stato arrestato; non è possibile ricevere tramite LPWSPRecv in un socket dopo che LPWSPShutdown è stato richiamato con come impostare su SD_RECEIVE o SD_BOTH. | |
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. | |
Il messaggio è stato troppo grande per adattarsi al buffer specificato e (solo per protocolli non affidabili) qualsiasi parte finale del messaggio che non è stata adattata al buffer. | |
Il socket non è stato associato (ad esempio, con LPWSPBind) o il socket non viene creato con il flag sovrapposto. | |
Il circuito virtuale è stato terminato a causa di un timeout o di un altro errore. | |
Il circuito virtuale è stato reimpostato dal lato remoto. | |
Socket s è orientato al messaggio e il circuito virtuale è stato chiuso correttamente dal lato remoto. | |
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
LPWSPRecv viene usato su socket connessi o socket senza connessione specificati dal parametro s e viene usato per leggere i dati in ingresso. L'indirizzo locale del socket deve essere noto. Questa operazione può essere eseguita in modo esplicito tramite LPWSPBind o implicitamente tramite LPWSPAccept, LPWSPConnect, LPWSPSendTo o LPWSPJoinLeaf.
Per i socket connessi senza connessione, questa funzione limita gli indirizzi da cui vengono accettati i messaggi ricevuti. La funzione restituisce solo messaggi dall'indirizzo remoto specificato nella connessione. I messaggi provenienti da altri indirizzi vengono eliminati in modo invisibile all'utente.
Per i socket sovrapposti LPWSPRecv viene usato per pubblicare uno o più buffer in cui i dati in ingresso verranno inseriti quando diventano disponibili, dopo il quale si verifica l'indicazione di completamento del client Windows Sockets SPI (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 LPWSPGetOverlappedResult.
Se sia lpOverlapped che lpCompletionRoutine sono Null, il socket in questa funzione verrà considerato come socket non sovrapposto.
Per i socket non sovrapposti, i parametri lpOverlapped, lpCompletionRoutine e lpThreadId vengono ignorati. Tutti i dati già ricevuti e memorizzati nel buffer dal trasporto verranno copiati nei buffer utente forniti. 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. Windows Sockets 2 non definisce alcun meccanismo di timeout di blocco standard per questa funzione. Per i protocolli che agiscono come protocolli di byte-stream, lo stack tenta di restituire il maggior numero possibile di dati soggetti allo spazio buffer fornito e alla quantità di dati ricevuti disponibili. Tuttavia, la ricezione di un singolo byte è sufficiente per sbloccare il chiamante. Non vi è alcuna garanzia che verrà restituito più di un singolo byte. Per i protocolli che fungono da messaggio orientato al messaggio, è necessario sbloccare il chiamante.
Se un protocollo agisce come flusso byte è determinato dall'impostazione di XP1_MESSAGE_ORIENTED e XP1_PSEUDO_STREAM nella relativa struttura WSAPROTOCOL_INFO e dall'impostazione del flag di MSG_PARTIAL passato a questa funzione (per i protocolli che lo supportano). Le combinazioni pertinenti vengono riepilogate nella tabella seguente (un asterisco (*) indica che l'impostazione di questo bit non è importante in questo caso).
XP1_MESSAGE_ORIENTED | XP1_PSEUDO_STREAM | MSG_PARTIAL | Agisce come |
---|---|---|---|
non impostato | * | * | flusso di byte |
* | set | * | flusso di byte |
set | non impostato | set | flusso di byte |
set | non impostato | non impostato | messaggio orientato |
I buffer forniti vengono compilati nell'ordine in cui vengono visualizzati nella matrice puntata da lpBuffers e i buffer vengono inseriti in modo che non vengano creati fori.
La matrice di strutture WSABUF a cui punta il parametro lpBuffers è temporanea. Se questa operazione viene completata in modo sovrapposto, è responsabilità del provider di servizi acquisire questa matrice di puntatori alle strutture WSABUF prima di restituire dalla chiamata. In questo modo, i client SPI di Windows Sockets creano matrici WSABUF basate sullo stack.
Per i socket in stile flusso di byte (ad esempio, digitare SOCK_STREAM), i dati in ingresso vengono inseriti nei buffer fino a quando non vengono riempiti i buffer, la connessione viene chiusa o i dati con buffer interno vengono esauriti. Indipendentemente dal fatto che i dati in ingresso riempiano tutti i buffer, l'indicazione di completamento si verifica per i socket sovrapposti. Per i socket orientati ai messaggi (ad esempio, digitare SOCK_DGRAM), un messaggio in ingresso viene inserito nei buffer forniti, fino alla dimensione totale dei buffer forniti e l'indicazione di completamento si verifica per i socket sovrapposti. Se il messaggio è maggiore dei buffer forniti, i buffer vengono riempiti con la prima parte del messaggio. Se la funzionalità MSG_PARTIAL è supportata dal provider di servizi, il flag di MSG_PARTIAL è impostato in lpFlags e le operazioni di ricezione successive possono essere usate per recuperare il resto del messaggio. Se MSG_PARTIAL non è supportato, ma il protocollo è affidabile, LPWSPRecv genera l'errore WSAEMSGSIZE e un'operazione di ricezione successiva con un buffer più grande può essere usato per recuperare l'intero messaggio. In caso contrario, il protocollo non è attendibile e non supporta MSG_PARTIAL), i dati in eccesso vengono persi e LPWSPRecv genera l'errore WSAEMSGSIZE.
Per i socket orientati alla connessione, LPWSPRecv può indicare la terminazione grazia del circuito virtuale in uno dei due modi, a seconda che il socket sia un flusso di byte o un messaggio orientato. Per i flussi di byte, zero byte che è stato letto indica la chiusura grazia e che non verranno mai letti più byte. Per i socket orientati ai messaggi, dove un messaggio di byte zero è spesso consentito, viene usato un codice di errore restituito di WSAEDISCON per indicare la chiusura graziata. In qualsiasi caso, si è verificato un codice di errore restituito di WSAECONNRESET .
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 dei valori seguenti.
Valore | Significato |
---|---|
MSG_PEEK | Visualizza 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 fuori banda (OOB). |
MSG_PARTIAL | Questo flag è solo per socket orientati ai messaggi. Nell'output indica che i dati forniti sono una parte del messaggio trasmesso dal mittente. Le parti rimanenti del messaggio verranno fornite nelle operazioni di ricezione successive. Un'operazione di ricezione successiva con MSG_PARTIAL flag deselezionata indica la fine del messaggio del mittente. Come parametro di input, MSG_PARTIAL indica che l'operazione di ricezione deve essere completata anche se solo parte di un messaggio è stata ricevuta dal provider di servizi. |
Se un'operazione sovrapposta viene completata immediatamente, LPWSPRecv 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, LPWSPRecv restituisce SOCKET_ERROR e indica il codice di errore WSA_IO_PENDING. In questo caso, lpNumberOfBytesRecvd e lpFlags non vengono aggiornati. 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 LPWSPGetOverlappedResult. I valori del flag vengono ottenuti tramite il parametro dwFlags della routine di completamento oppure esaminando il parametro lpdwFlags di WSAGetOverlappedResult.
I provider devono consentire la chiamata di questa funzione dall'interno della routine di completamento di una funzione LPWSPRecv precedente, LPWSPRecvFrom, LPWSPSend o LPWSPSendTo . Tuttavia, per un determinato socket, non è possibile annidare le routine di completamento di I/O. 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 contemporaneamente in sospeso, ognuna deve fare riferimento a una struttura sovrapposta separata. La struttura WSAOverlapped è definita nella propria pagina di riferimento.
Se il parametro lpCompletionRoutine è Null, il provider di servizi segnala il membro hEvent di lpOverlapped quando l'operazione sovrapposta viene completata se contiene un handle di oggetto evento valido. Il client SPI di Windows Sockets può usare LPWSPGetOverlappedResult per attendere o eseguire il polling nell'oggetto evento.
Se lpCompletionRoutine non è null, il membro hEvent viene ignorato e può essere usato dal client SPI di Windows Sockets per passare le informazioni di contesto alla routine di completamento. Un client che passa un valore null lpCompletionRoutine 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 membro hEvent non è definito e il tentativo di attendere il membro hEvent produce risultati imprevedibili.
È responsabilità del provider di servizi organizzare la chiamata della routine di completamento del client specificato al termine dell'operazione sovrapposta. Poiché la routine di completamento deve essere eseguita nel contesto dello stesso thread che ha avviato l'operazione sovrapposta, non può essere richiamata direttamente dal provider di servizi. Il Ws2_32.dll offre un meccanismo di chiamata asincrona (APC) per facilitare la chiamata alle routine di completamento.
Un provider di servizi prevede l'esecuzione di una funzione nel contesto di thread e processo appropriato chiamando WPUQueueApc, che è stato usato per avviare l'operazione sovrapposta. Questa funzione può essere chiamata da qualsiasi contesto di processo e thread, anche un contesto diverso dal thread e dal processo usato per avviare l'operazione sovrapposta.
WPUQueueApc accetta come parametri di input un puntatore a una struttura WSATHREADID (fornita al provider tramite il parametro di input lpThreadId ), un puntatore a una funzione APC da richiamare e un valore di contesto che viene successivamente passato alla funzione APC. Poiché solo un singolo valore di contesto è disponibile, la funzione APC stessa non può essere la routine di completamento specificata dal client. Il provider di servizi deve invece fornire un puntatore alla propria funzione APC che usa il valore di contesto fornito per accedere alle informazioni di risultato necessarie per l'operazione sovrapposta e quindi richiama la routine di completamento specificata dal client.
Il prototipo per la routine di completamento fornita dal client è il seguente.
void CALLBACK
CompletionRoutine(
IN DWORD dwError,
IN DWORD cbTransferred,
IN LPWSAOVERLAPPED lpOverlapped,
IN DWORD dwFlags
);
Il parametro CompletionRoutine è un segnaposto per un nome di funzione fornito dal client. dwError specifica lo stato di completamento dell'operazione sovrapposta, come indicato da lpOverlapped. Il parametro cbTransferred specifica il numero di byte ricevuti. dwFlags contiene informazioni che sarebbero state visualizzate in lpFlags se l'operazione di ricezione era stata completata immediatamente. Questa funzione non restituisce un valore.
Le routine di completamento possono essere chiamate in qualsiasi ordine, ma non necessariamente lo stesso ordine in cui vengono completate le operazioni sovrapposte. Tuttavia, i buffer pubblicati sono garantiti di essere compilati nello stesso ordine in cui vengono forniti.
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 .
Requisiti
Requisito | Valore |
---|---|
Client minimo supportato | Windows 10 Build 20348 |
Server minimo supportato | Windows 10 Build 20348 |
Intestazione | ws2spi.h |