xticks barplot python sockets

python - barplot - pandas plot



Cómo saber si una conexión está muerta en Python (5)

Desde el enlace publicado por Jweede:

excepción socket.timeout:

This exception is raised when a timeout occurs on a socket which has had timeouts enabled via a prior call to settimeout(). The accompanying value is a string whose value is currently always “timed out”.

Aquí están los programas de cliente y servidor de demostración para el módulo de socket de los documentos de python

# Echo server program import socket HOST = '''' # Symbolic name meaning all available interfaces PORT = 50007 # Arbitrary non-privileged port s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((HOST, PORT)) s.listen(1) conn, addr = s.accept() print ''Connected by'', addr while 1: data = conn.recv(1024) if not data: break conn.send(data) conn.close()

Y el cliente:

# Echo client program import socket HOST = ''daring.cwi.nl'' # The remote host PORT = 50007 # The same port as used by the server s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) s.send(''Hello, world'') data = s.recv(1024) s.close() print ''Received'', repr(data)

En la página de ejemplo de documentos que extraje, existen ejemplos más complejos que emplean esta idea, pero aquí está la respuesta simple:

Suponiendo que está escribiendo el programa del cliente, simplemente coloque todo el código que usa el socket cuando esté en riesgo de ser abandonado, dentro de un bloque de prueba ...

try: s.connect((HOST, PORT)) s.send("Hello, World!") ... except socket.timeout: # whatever you need to do when the connection is dropped

Quiero que mi aplicación de Python pueda saber cuándo se ha descartado el socket del otro lado. ¿Hay un método para esto?


Respuesta corta:

utilice un recv no bloqueante (), o un recv de bloqueo () / select () con un tiempo de espera muy corto.

Respuesta larga:

La forma de manejar las conexiones de socket es leer o escribir cuando lo necesite y estar preparado para manejar los errores de conexión.

TCP distingue entre 3 formas de "soltar" una conexión: tiempo de espera, restablecer, cerrar.

De estos, el tiempo de espera no se puede detectar realmente, TCP puede indicarle que el tiempo no ha expirado todavía. Pero incluso si te dijera eso, el tiempo podría expirar inmediatamente después.

Recuerde también que al usar shutdown (), usted o su compañero (el otro extremo de la conexión) pueden cerrar solo la secuencia de bytes entrantes y mantener la secuencia de bytes salientes en ejecución, o cerrar la secuencia saliente y mantener la entrada entrante.

Por lo tanto, en términos estrictos, desea verificar si la secuencia de lectura está cerrada o si la secuencia de escritura está cerrada o si ambas están cerradas.

Incluso si la conexión se "cayó", aún debería poder leer cualquier información que todavía esté en el búfer de red. Solo después de que el búfer esté vacío, recibirá una desconexión de recv ().

Comprobar si la conexión se eliminó es como preguntar "¿Qué recibiré después de leer todos los datos que están almacenados temporalmente en el búfer?" Para descubrirlo, solo tiene que leer todos los datos que están actualmente almacenados en buffer.

Puedo ver cómo "leer todos los datos almacenados en el búfer", para llegar al final, podría ser un problema para algunas personas, que todavía piensan en recv () como una función de bloqueo. Con un bloqueo de recv (), "bloquear" una lectura cuando el búfer ya está vacío se bloqueará, lo que frustra el propósito de "verificar".

En mi opinión, cualquier función que esté documentada para bloquear potencialmente todo el proceso indefinidamente es un error de diseño, pero creo que todavía está ahí por razones históricas, desde cuando usar un socket como un descriptor de archivo normal era una buena idea.

Lo que puedes hacer es:

  • establezca el socket en modo no bloqueante, pero obtendrá un error dependiente del sistema para indicar que el búfer de recepción está vacío, o que el búfer de envío está lleno
  • se adhieren al modo de bloqueo pero establecen un tiempo de espera de socket muy corto. Esto le permitirá "hacer ping" o "verificar" el socket con recv (), más o menos lo que quiere hacer
  • use select () call o asyncore module con un tiempo de espera muy corto. El informe de errores sigue siendo específico del sistema.

Para la parte de escritura del problema, mantener los búferes de lectura vacíos prácticamente lo cubre. Descubrirá una conexión "descartada" después de un intento de lectura no bloqueante, y puede optar por dejar de enviar algo después de que una lectura devuelva un canal cerrado.

Supongo que la única forma de asegurarse de que los datos enviados hayan llegado al otro extremo (y que aún no estén en el búfer de envío) es:

  • reciba una respuesta adecuada en el mismo socket para el mensaje exacto que envió. Básicamente está utilizando el protocolo de nivel superior para proporcionar confirmación.
  • realizar un shutdow () exitoso y cerrar () en el socket

El método de socket python dice que send () devolverá 0 bytes escritos si el canal está cerrado. Puede usar un socket.send () no bloqueado o un timeout y si devuelve 0 ya no puede enviar datos en ese socket. Pero si devuelve un valor distinto de cero, ya has enviado algo, buena suerte con eso :)

También aquí no he considerado los datos de socket OOB (fuera de banda) aquí como un medio para abordar su problema, pero creo que OOB no era lo que usted quiso decir.


Si no me equivoco, esto generalmente se maneja mediante un timeout .


Traducí el ejemplo de código en esta publicación de blog en Python: ¿Cómo detectar cuándo el cliente cierra la conexión? y funciona bien para mí:

from ctypes import ( CDLL, c_int, POINTER, Structure, c_void_p, c_size_t, c_short, c_ssize_t, c_char, ARRAY ) __all__ = ''is_remote_alive'', class pollfd(Structure): _fields_ = ( (''fd'', c_int), (''events'', c_short), (''revents'', c_short), ) MSG_DONTWAIT = 0x40 MSG_PEEK = 0x02 EPOLLIN = 0x001 EPOLLPRI = 0x002 EPOLLRDNORM = 0x040 libc = CDLL(None) recv = libc.recv recv.restype = c_ssize_t recv.argtypes = c_int, c_void_p, c_size_t, c_int poll = libc.poll poll.restype = c_int poll.argtypes = POINTER(pollfd), c_int, c_int class IsRemoteAlive: # not needed, only for debugging def __init__(self, alive, msg): self.alive = alive self.msg = msg def __str__(self): return self.msg def __repr__(self): return ''IsRemoteClosed(%r,%r)'' % (self.alive, self.msg) def __bool__(self): return self.alive def is_remote_alive(fd): fileno = getattr(fd, ''fileno'', None) if fileno is not None: if hasattr(fileno, ''__call__''): fd = fileno() else: fd = fileno p = pollfd(fd=fd, events=EPOLLIN|EPOLLPRI|EPOLLRDNORM, revents=0) result = poll(p, 1, 0) if not result: return IsRemoteAlive(True, ''empty'') buf = ARRAY(c_char, 1)() result = recv(fd, buf, len(buf), MSG_DONTWAIT|MSG_PEEK) if result > 0: return IsRemoteAlive(True, ''readable'') elif result == 0: return IsRemoteAlive(False, ''closed'') else: return IsRemoteAlive(False, ''errored'')


Depende de lo que quiere decir con "descartado". En el caso de los sockets TCP, si el otro extremo cierra la conexión ya sea close () o terminando el proceso, lo averiguará leyendo un final de archivo u obteniendo un error de lectura, normalmente el errno se establece en el restablecimiento de la conexión peer ''es por su sistema operativo. Para Python, leerá una cadena de longitud cero, o se lanzará un socket.error cuando intente leer o escribir desde el socket.