Enviar el objeto socket al proceso en ejecución bifurcado (multiprocessing.Queue)

Estoy aprendiendo a usar HTML5 WebSockets y, como parte de eso, estoy escribiendo un servidor en Python para que pueda conocer la esencia de cómo funcionan. El otro día creé uno que funcionó bastante bien, pero quería expandirlo para que admitiera múltiples puntos finales, ya que cada punto final es un “servicio” diferente que puede manejar clientes de websocket.

En este momento, mi implementación funciona con procesos de generación y otros (uso multiproceso en lugar de subprocesos, ya que leí que los subprocesos no son en realidad multihilo en CPython y eso es lo que creo que estoy usando (instalación predeterminada en Ubuntu 12.04)), pero Tengo problemas para enviar los sockets de clientes recibidos a los procesos de servicio.

Aquí es cómo los envío (esto se ejecuta en un bucle):

try: #get a new client conn, addr = server.accept() print "Client connected from", addr request = conn.recv(4096) response, close, service = self.handshake(request) conn.send(response) if close: print "Invalid request from", addr conn.close() continue client = WebSockets.WebSocketClient(conn, addr) service.clientConnQueue.put(client) 

‘servidor’ es un socket que escucha las conexiones entrantes. El método de handshake se encarga de validar su solicitud y de determinar en qué proceso de servicio colocar al cliente. ‘respuesta’ es la respuesta http a enviar, ‘cerrar’ es verdadero si hubo un error y ‘servicio’ es una clase que hereda de multiprocessing.Queue. WebSocktes.WebSocketClient es donde mi implementación de envío y recepción se almacena y básicamente funciona como un contenedor para un socket.

‘clientConnQueue’ se crea así:

 class Service(multiprocessing.Process): """Base class for all services.""" def __init__(self, manager): multiprocessing.Process.__init__(self) self.manager = manager self.clientConnQueue = self.manager.Queue() self.shutdownFlag = multiprocessing.Event() 

gestor es un multiproceso.Manager ()

El error que recibo cuando trato de colocar un cliente en el clientConnQueue es el siguiente:

 File "./WebSocketServer.py", line 183, in  main() File "./WebSocketServer.py", line 180, in main server.runServer() File "./WebSocketServer.py", line 67, in runServer service.clientConnQueue.put(client) File "", line 2, in put File "/usr/lib/python2.7/multiprocessing/managers.py", line 758, in _callmethod conn.send((self._id, methodname, args, kwds)) TypeError: expected string or Unicode object, NoneType found 

Entonces me sale un error de tubería rota en el lado receptor.

Recibí el mismo error cuando estaba usando un multiprocesamiento. La fecha para enviar la conexión y pensé que cambiarlo a una cola creada por un administrador arreglaría el problema. Sin embargo, parece hacer exactamente la misma implementación.

Claramente, esta no es la forma en que se supone que uno debe enviar algo como esto a un proceso en ejecución, entonces, ¿cuál es la forma correcta de enviar objetos no serializables a un proceso?

Pasar el socket a otro proceso no es algo trivial. Mire, por ejemplo, esta pregunta: ¿Puedo abrir un socket y pasarlo a otro proceso en Linux?

De todos modos, los procesos o subprocesos del sistema operativo no son lo que realmente desea para implementar el servidor websocket, debido a la gran sobrecarga de memoria. Mire a smth con sockets sin locking … por ejemplo, Tornado http://www.tornadoweb.org/documentation/websocket.html

Ha existido por más de 4 años, aunque requiere un poco de trabajo.

Las agallas se encuentran en multiprocessing.reduction, y los detalles de un ejemplo se pueden ver en este github gist .

No puede enviar sockets a procesos bifurcados sin usar magia profunda de Unix. Puede leer la Progtwigción avanzada del libro en el entorno Unix si realmente desea ver cómo se hace en C.

Para una solución fácil, cambie el uso de subprocesos y su código probablemente solo funcionará. Si bien el subprocesamiento no es perfecto en Python, es bastante bueno para hacer cosas de IO intensivo.

Alternativamente, cree su conector de escucha antes de bifurcar y obtenga todos los subprocesos para escuchar ( accept llamada). El sistema operativo se asegurará de que solo uno de ellos obtenga la conexión. Esta es la forma en que usualmente se escriben los servidores de preforking.

Si crea un zócalo antes del proceso de bifurcación, los niños heredarán su descriptor de archivo.