2013-07-13 4 views
6

Sto scrivendo un server TCP simultanee che deve gestire più connessioni con il 'thread per ogni connessione' approccio (usando un pool di filo). Il mio dubbio è su quale sia il modo più ottimale per ogni thread per ottenere un descrittore di file diverso.Calling accetta() da più thread

Ho trovato che i prossimi due metodi sono i più consigliati:

  1. Un filo conduttore che accepts() tutte le connessioni in entrata e esercizi i descrittori su una struttura di dati (es .: un queue). Quindi ogni thread è in grado di ottenere un file dalla coda.
  2. Accetta() è chiamato direttamente da ogni thread. (Consigliato in Unix Network Programming V1)

Problemi trovo a ciascuno di loro:

  1. La struttura dati statica che memorizza tutti i FD del devono essere bloccato (mutex_lock) prima che un thread può leggere da esso, quindi nel caso in cui un numero considerevole di thread voglia leggere nello stesso momento , non so quanto tempo passerebbe fino a quando tutti loro otterrebbero il loro obiettivo.
  2. Ho letto che il problema relativo al Thundering Herd simultanei accept() chiamate non è stato completamente risolto su Linux ancora, così forse avrei bisogno di creare una soluzione artificiale ad esso che finirebbe per rendere l'applicazione almeno altrettanto lento come con l'approccio 1.

Fonti:

(Alcuni link a parlare di approccio 2: does-the-thundering-herd-problem-exist-on-linux-anymore - e un articolo che ho trovato abo ut esso (obsoleto): linux-scalability/reports/accept.html

E un SO rispondere che raccomanda approccio 1: can-i-call-accept-for-one-socket-from-several-threads-simultaneously


Sono molto interessato sulla questione, in modo da apprezzerò alcuna opinione a questo proposito :)

risposta

3

Come menzionato nello StackOverflow answer che hai collegato, una chiamata thread singolo accept() è probabilmente la strada da percorrere. Si menzionano le preoccupazioni relative al blocco, ma in questi giorni si troveranno implementazioni di code senza blocco disponibili in Boost.Lockfree, Intel TBB e altrove. È possibile utilizzare uno di questi se lo si desidera, ma è possibile utilizzare solo una variabile di condizione per consentire ai thread di lavoro di dormire e riattivare uno di essi quando viene stabilita una nuova connessione.

+0

Grazie per l'idea della variabile di condizione, penso che possa rendere l'approccio abbastanza efficiente. Ad ogni modo vorrei sapere se il secondo approccio potrebbe essere fattibile o meno (solo per dissipare alcuni dei miei dubbi). (P.S.: Al momento non accetterò la tua risposta perché mi piacerebbe avere le opinioni di altre persone :)) – Str1101

+0

Il secondo approccio dovrebbe essere di rigore per qualsiasi implementazione di coda che scrivi per questo scenario comunque. Se non si utilizza un condvar interno alla coda, i thread client vengono ridotti al polling costante per vedere se ci sono dati quando ciò che si vuole veramente è che dormano finché non c'è qualcosa da fare, cioè bloccare quando non c'è nulla nella coda leggere. – Duck