Relé de datos basados ​​en el kernel (Linux) entre dos sockets TCP

escribíServidor de retransmisión TCP que funciona como enrutador peer-to-peer (supernodo).

El caso más simple son dos sockets abiertos y transmisión de datos entre ellos:

clienteA <---> servidor <---> clienteB

Sin embargo, el servidor tiene que servir alrededor de 2000 pares A-B, es decir. 4000 enchufes ...

Hay dos implementaciones de retransmisión de flujo de datos bien conocidas enusuario (Residencia ensocketA.recv () -> socketB.send () ysocketB.recv () -> socketA.send ()):

usando deseleccionar / encuesta Funciones (método sin bloqueo)Uso de hilos / horquillas (método de bloqueo).

Utilicé subprocesos, por lo que en el peor de los casos, el servidor crea 2 * 2000 subprocesos. Tuve que limitar el tamaño de la pila y funciona, pero ¿es la solución correcta?

Núcleo de mi pregunta:

¿Hay alguna forma de evitar la transmisión activa de datos entre dos sockets en la zona de usuario?

Parece que hay un camino pasivo. Por ejemplo, puedo crear un descriptor de archivo desde cada socket, crear dos tuberías y usar dup2 () - el mismo método como redireccionamiento de entrada / salida estándar. Entonces, dos hilos no sirven para la transmisión de datos y se pueden finalizar / cerrar.¿La pregunta es si el servidor debería cerrar sockets y tuberías y cómo saber cuándo se rompe la tubería para registrar el hecho?

También he encontrado "pares de zócalos", pero no estoy seguro de ello para mi propósito.

¿Qué solución recomendaría para descargar la zona de usuario y limitar la cantidad de subprocesos?

Algunas explicaciones adicionales:

El servidor ha definido una tabla de enrutamiento estática (por ejemplo, ID_A con ID_B - identificadores emparejados). El cliente A se conecta al servidor y envía ID_A. Luego, el servidor espera al cliente B. Cuando A y B están emparejados (ambos sockets abiertos), el servidor inicia la transmisión de datos.Los clientes son dispositivos simples detrás de NAT simétricos, por lo que el protocolo N2N o las técnicas de NAT transversal son demasiado complejos para ellos.

Gracias a Gerhard Rieger tengo la pista:

Soy consciente de dos formas en el espacio del kernel para evitar la lectura / escritura, la grabación / el envío en el espacio del usuario:

enviar archivoempalme

Ambos tienen restricciones con respecto al tipo de descriptor de archivo.

dup2 no ayudará a hacer algo en el kernel, AFAIK.

Páginas de manual:empalme (2) empalme (2) vmsplice (2) archivo de envío (2) tee (2)

Enlaces relacionados:

Entendiendo sendfile () y 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 () y send () diferencia?puente entre dos descriptores de archivoEnvíe y reciba un archivo en la programación de socket en Linux con C / C ++ (GCC / G ++)http://ogris.de/howtos/splice.html

Respuestas a la pregunta(2)

Su respuesta a la pregunta