2011-03-26 20 views
9

Lo que intento resolver: tener un servidor TCP de Erlang que escuche en un puerto específico (el código debe residir en algún tipo de interfaz externa/API) y cada conexión entrante debe ser manejada por un gen_server (es decir, incluso el gen_tcp:accept debe estar codificado dentro del gen_server), pero en realidad no quiero generar inicialmente un número predefinido de procesos que acepte una conexión entrante). ¿Es eso de alguna manera posible?Erlang aceptar dinámicamente conexiones tcp entrantes

Respuesta

8

Usted debe tener una estática gen_server (o cualquier otro proceso) que escucha conexiones entrantes utilizando accept y cada vez que reciba una conexión, decirle a un supervisor para desovar de un trabajador gen_server. Obtenga el pid para este proceso, llame al gen_tcp:controlling_process/2 con ese pid y luego envíe el socket que obtuvo de accept a ese proceso (debe hágalo en ese orden, de lo contrario, el nuevo proceso podría usar el socket antes de que se haya entregado) .

El proceso de escucha solo debe tener una responsabilidad, y eso es escuchar nuevas conexiones. Por eso, no importa si bloquea, por lo que podría ser un gen_server o cualquier otro proceso. De hecho, probablemente sea excesivo tenerlo como gen_server, sería más simple y más rápido comenzar un proceso bare-bone proc_lib en su lugar.

+0

Gracias, voy a probar este enfoque, ya que parece el más factible – hyperboreean

4

El problema con gen_tcp:accept es que bloquea, por lo que si lo llama dentro de un gen_server, bloquea el servidor para que no reciba otros mensajes. Puede tratar de evitar esto pasando un tiempo de espera pero, en última instancia, equivale a una forma de votación que es mejor evitar. En cambio, puede intentar Kevin Smith's gen_nb_server en su lugar; usa una función interna no documentada prim_inet:async_accept y otras funciones prim_inet para evitar el bloqueo.

+0

Pero si puedo encontrar una forma de retransmitir el 'gen_tcp: accept' dentro de su gen_server, no me importaría que esté bloqueando. Pero supongo que no es posible saber por adelantado (digamos desde 'gen_tcp: listen') que tiene una conexión entrante que debe aceptar. Gracias por el puntero a 'gen_nb_server'! ¿Lo has usado en producción? – hyperboreean

+0

No creo que necesite 'gen_nb_server' para lo que está haciendo. Tu caso es muy simple. –

+1

Nunca he usado 'gen_nb_server' en producción pero he usado' prim_inet: async_accept' en producción. –

1

Deberías usar "prim_inet: async_accept (Listen_socket, -1)" como dice Steve. Ahora la conexión entrante sería aceptada por su call_info callback (asumiendo que su interfaz también es un gen_server) ya que ha usado una llamada asincrónica accept.

Al aceptar la conexión que puede generar otra ger_server (recomendaría gen_fsm) y hacer que a medida que el "proceso de control" llamando "gen_tcp: controlling_process (CliSocket, pid del proceso spwned)".

Después de esto, todos los datos del socket serían recibidos por ese proceso en lugar de por su código de interfaz. Al igual que un nuevo proceso de control se generará para otra conexión.

+0

Simplemente corte y pegue desde otro lugar sin atribución. –

+0

Sí, lo he cortado y pegado desde mi propia aplicación erlang. ¿Necesito tomar permiso de mí para eso? – Arunmu

+1

Lo siento, parecía un fragmento de un diálogo de lista de correo en la primera vista. –

Cuestiones relacionadas