Condividi tramite


Routine di blocco e EINPROGRESS di Windows Sockets 1.1

Un problema importante nella conversione di applicazioni da un ambiente Berkeley Sockets a un ambiente Windows comporta il blocco; vale a dire, richiamando una funzione che non restituisce fino al completamento dell'operazione associata. Si verifica un problema quando il completamento dell'operazione richiede arbitrariamente molto tempo: un esempio è una funzione recv, che potrebbe bloccare fino a quando i dati non vengono ricevuti dal sistema peer. Il comportamento predefinito all'interno del modello Berkeley Sockets prevede che un socket funzioni in modalità di blocco, a meno che il programmatore non richieda esplicitamente che le operazioni vengano considerate non bloccanti. Gli ambienti Windows Sockets 1.1 non potevano preemptive scheduling. Pertanto, è consigliabile che i programmatori usino le operazioni non bloccanti (asincrone) se possibile con Windows Sockets 1.1. Poiché ciò non è sempre possibile, sono state fornite le strutture di pseudo-blocco descritte di seguito.

Nota

Windows Sockets 2 viene eseguito solo in sistemi operativi a 32 bit preemptive in cui i deadlock non sono un problema. Le procedure di programmazione consigliate per Windows Sockets 1.1 non sono necessarie in Windows Sockets 2.

 

Anche in un socket di blocco, alcune funzioni , associare, getockopte getpeername, ad esempio, completate immediatamente. Non esiste alcuna differenza tra un blocco e un'operazione non bloccante per tali funzioni. Altre operazioni, ad esempio recv, possono completare immediatamente o richiedere un tempo arbitrario, a seconda di varie condizioni di trasporto. Se applicato a un socket di blocco, queste operazioni vengono definite operazioni di blocco. Le funzioni seguenti possono bloccare:

Con Windows Sockets 1.1 a 16 bit, un'operazione di blocco che non può essere completata immediatamente viene gestita da pseudoblocche come indicato di seguito.

Il provider di servizi avvia l'operazione, quindi immette un ciclo in cui invia tutti i messaggi di Windows (che restituisce il processore a un altro thread, se necessario) e quindi verifica il completamento della funzione Windows Sockets. Se la funzione è stata completata o se WSACancelBlockingCall, la funzione di blocco viene completata con un risultato appropriato.

Un provider di servizi deve consentire l'installazione di una funzione hook di blocco che non elabora i messaggi per evitare la possibilità di messaggi rientranti mentre un'operazione di blocco è in sospeso. La funzione hook di blocco più semplice restituisce FALSE. Se una DLL di Windows Sockets dipende dai messaggi per l'operazione interna, può eseguire PeekMessage(hMyWnd...) prima di eseguire l'hook di blocco dell'applicazione in modo che possa ottenere i messaggi senza influire sul resto del sistema.

In un ambiente Windows Sockets 1.1 a 16 bit, se viene ricevuto un messaggio di Windows per un processo per il quale è in corso un'operazione di blocco, esiste il rischio che l'applicazione tenti di eseguire un'altra chiamata a Windows Sockets. A causa della difficoltà di gestione di questa condizione in modo sicuro, Windows Sockets 1.1 non supporta tale comportamento dell'applicazione. Un'applicazione non è autorizzata a eseguire più chiamate di funzione Windows Sockets annidate. Per una determinata attività è consentita una sola chiamata di funzione in sospeso. Le uniche eccezioni sono due funzioni fornite per aiutare il programmatore in questa situazione: WSAIsBlocking e WSACancelBlockingCall.

La funzioneWSAIsBlockingpuò essere chiamata in qualsiasi momento per determinare se è in corso una chiamata di Windows Sockets 1.1 bloccante. Analogamente, la funzione di WSACancelBlockingCall può essere chiamata in qualsiasi momento per annullare una chiamata di blocco in corso. Qualsiasi altra annidazione di funzioni Windows Sockets ha esito negativo e viene visualizzato l'errore WSAEINPROGRESS.

È consigliabile sottolineare che questa restrizione si applica sia alle operazioni di blocco che a operazioni non bloccanti. Per le applicazioni Windows Sockets 2 che negoziano la versione 2.0 o successiva al momento della chiamata di WSAStartup, non viene chiusa alcuna restrizione sull'annidamento delle operazioni. Le operazioni possono essere annidate in rare circostanze, ad esempio durante un WSAAccept callback di accettazione condizionale o se un provider di servizi richiama a sua volta una funzione Windows Sockets 2.

Sebbene questo meccanismo sia sufficiente per applicazioni semplici, non può supportare i requisiti complessi di invio di messaggi di applicazioni più avanzate, ad esempio quelle che usano il modello MDI. Per tali applicazioni, l'API Windows Sockets include la funzione WSASetBlockingHook, che consente all'applicazione di specificare una routine speciale che può essere chiamata anziché la routine di invio dei messaggi predefinita descritta nella discussione precedente.

Il provider Windows Sockets chiama l'hook di blocco solo se sono soddisfatte tutte le condizioni seguenti:

  • La routine è una classe definita come in grado di bloccare.
  • Il socket specificato è un socket di blocco.
  • Impossibile completare immediatamente la richiesta.

Un socket è impostato sul blocco per impostazione predefinita, ma la funzione ioctlsocket con il FIONBIO IOCTL o la funzione WSAAsyncSelect può impostare un socket in modalità non bloccante.

L'hook di blocco non viene mai chiamato e l'applicazione non deve preoccuparsi dei problemi di reinsezione che l'hook di blocco può introdurre, se un'applicazione segue queste linee guida:

  • Usa solo socket non bloccanti.
  • Usa la WSAAsyncSelect e/o le routine di WSAAsyncGetXByY anziché selezionare e le routine getXbyY.

Se un'applicazione Windows Sockets 1.1 richiama un'operazione asincrona o non bloccante che accetta un puntatore a un oggetto memoria (un buffer o una variabile globale, ad esempio) come argomento, è responsabilità dell'applicazione assicurarsi che l'oggetto sia disponibile per Windows Socket in tutta l'operazione. L'applicazione non deve richiamare alcuna funzione di Windows che potrebbe influire sul mapping o sull'indirizzabilità della memoria interessata.