Sto imparando a utilizzare HTML5 WebSockets e come parte di ciò sto scrivendo un server in Python in modo da poter conoscere il nocciolo duro di come funzionano. Ne ho creato uno l'altro giorno che funzionava abbastanza bene, ma volevo espanderlo in modo tale che potesse supportare più endpoint con ogni endpoint che fosse un "servizio" diverso in grado di gestire i client websocket.Invia oggetto socket a processo in esecuzione biforcuta (multiprocessing.Queue)
Al momento, la mia implementazione funziona con processi di spawning e così via (sto usando multiprocessing anziché threading da quando ho letto che il threading non è realmente multithreading in CPython e questo è quello che penso sto usando (installazione predefinita su Ubuntu 12.04)), ma sto riscontrando problemi nell'invio dei socket client ricevuti ai processi di servizio.
Ecco come li rimando (questo viene eseguito in un ciclo):
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)
'server' è una presa in ascolto per le connessioni in entrata. Il metodo di handshake si occupa di convalidare la loro richiesta e determinare quale processo di servizio inserire il cliente. 'response' è la risposta http da inviare, 'close' è True se c'è stato un errore, e 'service' è una classe che eredita da multiprocessing.Queue. WebSocktes.WebSocketClient è dove la mia invio e la ricezione di attuazione viene memorizzato e fondamentalmente funziona come un wrapper per una presa di corrente.
'clientConnQueue' si crea in questo modo:
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()
manager è un multiprocessing.Manager()
L'errore che ottengo quando provo a mettere un cliente nel clientConnQueue è la seguente:
File "./WebSocketServer.py", line 183, in <module>
main()
File "./WebSocketServer.py", line 180, in main
server.runServer()
File "./WebSocketServer.py", line 67, in runServer
service.clientConnQueue.put(client)
File "<string>", 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
Ho quindi un errore di tubo rotto sul lato di ricezione.
Ho ricevuto lo stesso errore quando stavo usando un multiprocessing.Queue per inviare la connessione e ho pensato che modificarlo in una coda creata da un gestore avrebbe risolto il problema. Tuttavia, sembra fare esattamente la stessa implementazione.
Chiaramente questo non è il modo in cui si suppone di inviare qualcosa di simile a un processo in esecuzione, quindi qual è il modo corretto per inviare oggetti non serializzabili a un processo?
Ogni socket client non avrà necessariamente il proprio thread, ma ogni servizio ottiene il proprio processo/thread e viene lasciato al servizio esattamente cosa fare con il socket. Questo è un buon punto anche se ... i server http non hanno a che fare con la possibilità di 1000 connessioni simultanee di lunga durata e questo è un sovraccarico di memoria se ogni connessione ha il suo thread. –