2012-05-18 24 views
34

In un primo momento, devo chiedere quale sia il migliore in quali stati? Ad esempio un server MMORPG in tempo reale. Cosa succede se creo un thread per client invece di utilizzare socket non bloccanti? O cosa succede se uso un thread che contiene tutti i socket non bloccanti? Puoi spiegarmi i vantaggi?Perché dovrei usare socket non bloccanti o bloccanti?

risposta

29

Questa domanda merita una discussione più lungo ma ecco un breve pugnalata a una risposta:

  • socket bloccanti significa che una sola presa può essere attivo in qualsiasi momento in qualsiasi filo (perché blocca durante l'attesa per l'attività)
  • socket bloccanti è generalmente più facile che non bloccanti (programmazione asincrona tende ad essere più complicato)
  • si potrebbe creare 1 thread per presa come indicato ma fili hanno testa e sono estremamente inefficiente rispetto agli soluzioni non bloccanti;
  • con prese non-blocking si potrebbe gestire un volume molto più grande di clienti: potrebbe scalare a centinaia di migliaia in un singolo processo - ma il codice diventa un po 'più complicata

Con i socket non bloccanti (su Windows) si dispone di un paio di opzioni:

  • polling
  • eventi basati
  • I sovrapposta/O

I/O sovrapposti offrono le migliori prestazioni (migliaia di socket/processo) a scapito del modello più complicato da comprendere e implementare correttamente.

Fondamentalmente si tratta di prestazioni e complessità di programmazione.

NOTA

Ecco una migliore spiegazione del perché si utilizza un modello di thread/presa è una cattiva idea:

In Windows, la creazione di un gran numero di thread è altamente inefficiente, perché lo scheduler è in grado di determinare correttamente quali thread devono ricevere il tempo del processore e quali no. Ciò, unito al sovraccarico della memoria di ciascun thread, significa che si esauriranno la memoria (a causa dello spazio di stack) e i cicli del processore (a causa dell'overhead nella gestione dei thread) a livello di sistema operativo molto prima che si esaurisca la capacità di gestire le connessioni socket .

+0

Se si sta eseguendo su una scatola di 80 modo, si può strappare centinaia di fili non è un problema. –

+0

@John - Solo perché è possibile creare centinaia di thread (se hai abbastanza memoria) non significa che sia una buona idea. In effetti è una cattiva idea! –

+9

Il mio punto, certamente non ben fatto, è che non si può semplicemente tracciare una linea arbitraria a 20 e chiamare qualsiasi numero di thread oltre quel "cattivo". –

8

Andrò a verbale dicendo che per quasi qualsiasi cosa eccetto i programmi giocattolo, è necessario utilizzare socket non bloccanti come una cosa ovvia.

Le prese di blocco causano un problema grave: se la macchina all'altra estremità (o qualsiasi parte della connessione ad essa) non riesce durante una chiamata di blocco, il codice finirà bloccato fino al timeout dello stack IP. In un caso tipico, sono circa 2 minuti, il che è completamente inaccettabile per la maggior parte degli scopi. L'unico modo in per interrompere la chiamata di blocco è terminare il thread che lo ha prodotto, ma terminare un thread è quasi sempre inaccettabile, in quanto è praticamente impossibile ripulirlo e recuperare le risorse assegnate.Gli zoccoli non bloccanti rendono banale l'interruzione di una chiamata quando/se necessario, senza facendo qualcosa al thread che ha effettuato la chiamata.

È possibile eseguire prese di blocco con una sorta di pozzo se si utilizza invece un modello multi-processo. Qui, si genera semplicemente un processo completamente nuovo per ogni connessione. Quel processo usa un socket di blocco, e quando/se qualcosa va storto, basta uccidere l'intero processo. Il sistema operativo sa come ripulire le risorse da un processo, quindi la pulizia non è un problema. Tuttavia ha ancora altri potenziali problemi: 1) è necessario un monitor di processo per uccidere i processi quando necessario, e 2) generare un processo è in genere un po 'più costoso della semplice creazione di un socket. Tuttavia, questo può essere una valida opzione, soprattutto se:

  1. Hai a che fare con un piccolo numero di connessioni alla volta
  2. È generalmente svariati processi di lavorazione per ogni connessione
  3. Hai a che fare solo con ospiti locali in modo che il collegamento a loro è veloce e affidabile
  4. Sei più interessato a ottimizzare lo sviluppo di esecuzione

1. Beh, tecnicamente non è il modo solo possibile, ma la maggior parte delle alternative sono relativamente brutte - per essere più specifici, penso che quando aggiungerai il codice per capire che c'è un problema, e poi risolvi il problema, probabilmente hai fatto più lavoro extra rispetto a quando usi un socket non bloccante.

+6

È possibile interrompere un'operazione socket bloccata senza terminare il thread bloccato disconnettendo il socket da un altro contesto di thread. Ciò causerà il fallimento dell'operazione bloccata con un codice di errore, quindi il thread bloccato può spostarsi e fare altre cose, come la normale pulizia. –

Problemi correlati