2012-06-24 23 views
8

Tengo un problema de diseño:Python: ¿Socket and Threads?

Tengo dos hilos, un hilo de latido/control y un hilo de manejador de mensajes.

Ambos comparten el mismo socket, sin embargo, el hilo messageHandler solo envía mensajes y nunca los recibe. El hilo del latido envía y recibe (recibe mensajes y reacciona en latidos del corazón).

El problema es que no estoy seguro si esto es seguro. No hay ningún mecanismo, yo mismo, implementado para ver si el socket está siendo utilizado. Entonces, ¿compartir un socket sobre python es automáticamente seguro o no?

Además, si no es así, la razón por la que los puse en un hilo separado es porque el latido del corazón es más importante que el manejo de mensajes. Esto significa que si se inunda con mensajes, todavía necesita hacer un latido del corazón. Entonces, si tengo que implementar un cerrojo, ¿puedo priorizar si el hilo de mi latido/control necesita enviar un latido?

Respuesta

4

Desafortunadamente, el socket compartido por multi-hilo no es seguro para subprocesos. Piense en el búfer que dos subprocesos operan sin bloqueo.

La forma normal de implementarlo es con dos conectores, al igual que el ftp does.cmd socket y msg socket.

Si desea implementar esto en un socket, puede poner diferentes tipos de mensajes en colas diferentes, y con un tercer hilo consume la cola y enviarlos a través del único socket.

De esta manera, puede controlar el latido del corazón msg priory al msg de datos.

+1

¿Leer en un hilo y enviar desde otro hilo es seguro para subprocesos? – Colateral

0

No sé de una manera de priorizar en el nivel de Python.

Así que sugeriría utilizar 2 procesos, no hilos, y priorizar en el nivel del sistema operativo. En Unix puede usar os.nice() para hacer eso.

Tendría que usar 2 sockets entonces, y su problema de uso compartido se resolvería al mismo tiempo.

0

Si ambos hilos son subprocesos del cliente, es una buena idea abrir dos sockets de cliente uno para el servidor para el latido del corazón y otro para la comunicación.

8

Una mejor manera en lugar de utilizar un tercer hilo es usar threading.Lock() para proteger el recurso socket porque esto elimina la necesidad de un tercer hilo. Tiene una sobrecarga menor y menos latencia que si tuviera un tercer hilo.

import threading 

lock = threading.Lock() 

def sendfunction(sock, data): 
    with lock: 
     sock.send(data) 

Usted puede llamar a que a partir de cualquiera de sus hilos, pero sólo se permitirá un hilo a la hora de llamar sock.send. Cuando un hilo alcanza el bloqueo que ya está bloqueado por otro hilo, se suspenderá hasta que el otro hilo libere el bloqueo, luego adquirirá el bloqueo y el proceso se repetirá.

El módulo threading contiene Lock, RLock, y Condition que son todos muy útil cuando se trata de múltiples hilos y encontrará que vale la pena su tiempo para familiarizarse con ellos y su uso.

Puede incorporar el latido en el manejo de sus mensajes comprobando la hora actual con la última vez que envió un latido antes de procesar cada mensaje, y eso evitaría que se inunden los mensajes y no envíe un latido. El problema es que si el código de manejo de mensajes no se ejecuta, no se enviarán latidos. Podría aliviar esto haciendo que su código de manejo de mensaje obtenga un mensaje ficticio en intervalo para permitirle verificar si necesita enviar un latido y simplemente ignorar el mensaje ficticio.

Debe tratar de usar hilos con moderación (apunte a un único hilo), sin embargo, en su caso un hilo probablemente estaría bien, ya que va a pasar la mayor parte del tiempo durmiendo. Sin embargo, no debe utilizar un hilo daemon porque no se apaga correctamente. Aunque el daño puede ser inexistente en su caso si no se apaga correctamente, aún puede arrojar algún tipo de falla (mensaje de error) que se ve mal.

No estoy de acuerdo con el método de enchufes múltiples ya que creo que realmente complicaría la situación. Encontrará muchos tipos de servicios/aplicaciones de red que incorporan el latido y los mensajes en un solo flujo de bytes de socket.