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 come 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é questo non era sempre possibile, sono state fornite le strutture pseudo-bloccaggio 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, ad esempio bind, getsockopt e getpeername , vengono completate immediatamente. Non esiste alcuna differenza tra un blocco e un'operazione non bloccante per tali funzioni. Altre operazioni, ad esempio recv, possono essere completate 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 pseudo-blocco 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 è stata richiamata, 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 di nuovo ingresso 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, è possibile 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 può eseguire più di una chiamata di funzione Windows Sockets annidata. 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 funzione WSAIsBlocking può essere chiamata in qualsiasi momento per determinare se è in corso una chiamata di Windows Sockets 1.1 bloccante. Analogamente, la funzione WSACancelBlockingCall può essere chiamata in qualsiasi momento per annullare una chiamata di blocco in corso. Qualsiasi altra annidamento delle funzioni di Windows Sockets ha esito negativo e viene visualizzato l'errore WSAEINPROGRESS.

È opportuno 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 a WSAStartup, nessuna restrizione sull'annidamento delle operazioni viene chiusa. Le operazioni possono essere annidate in rare circostanze, ad esempio durante un callback di accettazione condizionale WSAAccept o se un provider di servizi richiama a sua volta una funzione Windows Sockets 2.

Sebbene questo meccanismo sia sufficiente per le 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 vere tutte le condizioni seguenti:

  • La routine è una classe definita come in grado di bloccare.
  • Il socket specificato è un socket di blocco.
  • La richiesta non può essere completata immediatamente.

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

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

  • Usa solo socket non bloccanti.
  • Usa le routine WSAAsyncSelect e/o WSAAsyncGetXByY invece di 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 sulla redditività degli indirizzi della memoria interessata.