2013-07-11 8 views
6

Ho scritto server di inoltro TCP che funziona come router peer-to-peer (supernodo).relay di dati basato su kernel (Linux) tra due socket TCP

Il caso più semplice sono due prese aperte e relè di dati tra di loro:

clientâ < ---> di server < ---> clientB

Tuttavia il server deve servire circa 2000 come AB coppie, es. 4000 prese ...

Ci sono due noti implementazioni relè flusso di dati in userland (basato su socketA.recv() -> socketB.send() e socketB.recv() -> socketA.send()):

  • utilizzando dei selezionare/rapido funzioni (non bloccante metodo)
  • utilizzando dei fili/forcelle (metodo di blocco)

ho usato le discussioni così nel peggiore dei casi il server crea 2 * 2000 discussioni! Ho dovuto limitare le dimensioni dello stack e funziona, ma è la soluzione giusta?

Nucleo della mia domanda:

C'è un modo per evitare l'inoltro dei dati attivi tra le due prese in spazio utente?

sembra che ci sia un modo passivo. Ad esempio, posso creare un descrittore di file da ciascun socket, creare due pipe e usare dup2() - lo stesso metodo come reindirizzamento stdin/out. Quindi due thread sono inutili per il relay di dati e possono essere completati/chiusi. La domanda è se il server dovrebbe mai chiudere prese e tubi e sapere come si rompono i tubi per registrare il fatto?

Ho anche trovato "Socket coppie", ma non sono sicuro su di esso per il mio scopo.

Quale soluzione sarebbe una consulenza off-caricare l'userland e la quantità limite di fo le discussioni?

Alcune spiegazioni aggiuntivi:

  • Il server ha definito la tabella di routing statico (ad esempio ID_A con ID_B - identificatori accoppiato.). Il client A si connette al server e invia ID_A. Quindi il server attende il client B. Quando A e B sono accoppiati (entrambi i socket aperti) il server avvia il relay dei dati.
  • I client sono semplici dispositivi dietro NAT simmetrico, pertanto il protocollo N2N o le tecniche NAT traversal sono troppo complessi per loro.

Grazie a Gerhard Rieger ho il suggerimento:

Sono a conoscenza di due modi spazio del kernel per evitare di lettura/scrittura, recv/inviare nello spazio utente:

  • sendfile
  • splice

Entrambi hanno restrizioni riguardanti il ​​tipo di descrittore di file.

dup2 non aiuterà a fare qualcosa nel kernel, AFAIK.

pagine man: splice(2)splice(2)vmsplice(2)sendfile(2)tee(2)

Link correlati:

+1

Per quel numero di connessioni, una combinazione di alcuni thread e ['epoll (4)'] (http://linux.die.net/man/4/epoll) è probabilmente qualcosa da esaminare. –

+1

Questo e potresti usare qualcosa come [libev] (http://software.schmorp.de/pkg/libev.html) – Hasturkun

+0

Grazie. Comunque è ancora un relay attivo in userland. Credo che esista un metodo passivo. Il server attende l'ID del client con timeout di 5 secondi, quindi i thread sembrano essere la scelta naturale per lo stage di accoppiamento. – nopsoft

risposta

3

Anche per carichi molto piccoli come 2000 connessioni simultanee, I' d non andare mai con i fili. Hanno lo stack più alto e il sovraccarico di commutazione, semplicemente perché è sempre più costoso assicurarsi di poter essere interrotto ovunque rispetto a quando si può essere interrotti solo in determinati luoghi. Basta usare epoll() e splice (se i tuoi socket sono TCP, che sembra essere il caso) e starai bene.Puoi persino eseguire epoll nella modalità di attivazione degli eventi, dove puoi registrare i tuoi fds una sola volta.

Se si desidera utilizzare assolutamente thread, utilizzare un thread per core della CPU per distribuire il carico, ma se è necessario farlo, significa che si sta giocando a velocità in cui l'affinità, la posizione della RAM su ogni socket della CPU, ecc. .. svolge un ruolo significativo, che non sembra essere il caso nella tua domanda. Quindi presumo che un singolo thread sia più che sufficiente nel tuo caso.

+0

Grazie. Meglio usare EPOLLONESHOT o ADD/DEL? Mi piace qui http://stackoverflow.com/questions/4173024/question-about-epoll-and-splice o http://rg4.net/archives/375.html? – nopsoft

+0

Mai provato EPOLLONESHOT, sebbene possa essere utile e forse un'alternativa elegante a EPOLLET. Inizia con lo standard ADD/DEL per limitare la complessità che penso e cercare di ottimizzare in seguito, se necessario. –

Problemi correlati