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:
- Understanding sendfile() and splice()
- http://blog.superpat.com/2010/06/01/zero-copy-in-linux-with-sendfile-and-splice/
- http://yarchive.net/comp/linux/splice.html (Linus)
- C, sendfile() and send() difference?
- bridging between two file descriptors
- Send and Receive a file in socket programming in Linux with C/C++ (GCC/G++)
- http://ogris.de/howtos/splice.html
Per quel numero di connessioni, una combinazione di alcuni thread e ['epoll (4)'] (http://linux.die.net/man/4/epoll) è probabilmente qualcosa da esaminare. –
Questo e potresti usare qualcosa come [libev] (http://software.schmorp.de/pkg/libev.html) – Hasturkun
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