sockets python-2.7 runtime-error shutdown

sockets - Cómo cerrar correctamente el socket tanto en el cliente como en el servidor(python)



python-2.7 runtime-error (1)

Estoy escribiendo 2 scripts en python.

  1. Client.py
  2. Server.py

Hay un socket entre el cliente y el servidor. El escenario es este:
Tengo un cliente que pide cerrar el programa, por lo tanto, debería informar al servidor que para entonces informará al otro cliente, por lo tanto, necesito cerrar el socket del cliente (1) al servidor y luego cerrar el socket del servidor a otro cliente (imagínese un juego de 2 personas a las que se les pide que salgan del juego).

Lo estoy haciendo así. En Client.py:

# send the request to the server eNum, eMsg = Protocol.send_all(self.socket_to_server, msg) if eNum: sys.stderr.write(eMsg) self.close_client() self.socket_to_server.shutdown(socket.SHUT_WR) exit(0)

luego en el código de Server.py:

# get the msg from the client that calleds num, msg = Protocol.recv_all(self.players_sockets[0]) # case of failure if num == Protocol.NetworkErrorCodes.FAILURE: sys.stderr.write(msg) self.shut_down_server() # case it was disconnected if num == Protocol.NetworkErrorCodes.DISCONNECTED: print msg self.shut_down_server() technical_win = ("exit" == msg) # send the msg to the client needed to call eNum, eMsg = Protocol.send_all(self.players_sockets[1],msg) if eNum: sys.stderr.write(eMsg) self.shut_down_server() # case end of game (winning or asking to exit) if technical_win: self.shut_down_server()

mientras self.shut_down_server() es:

def shut_down_server(self): # close socket of one of the player self.players_sockets[0].shutdown(socket.SHUT_RDWR) self.players_sockets[0].close() # close socket of one of the player self.players_sockets[1].shutdown(socket.SHUT_RDWR) self.players_sockets[1].close() # clean up exit(0)

Cuando el servidor envía el mensaje que el otro jugador pide para salir del cliente, obténgalo y haciendo lo mismo que mostré al principio.

desafortunadamente no funciona porque cuando el servidor realiza el código:

num, msg = Protocol.recv_all(self.players_sockets[0]) # case of failure if num == Protocol.NetworkErrorCodes.FAILURE: sys.stderr.write(msg) self.shut_down_server() # case it was disconnected if num == Protocol.NetworkErrorCodes.DISCONNECTED: print msg self.shut_down_server()

entra en el segundo si e imprime ''ERROR - Could not receive a message: timed out.''

¿Cómo soluciono esto correctamente?

PD

Estoy usando Linux


Parece que lo que estás buscando es un cierre elegante. Primero, su código no funciona porque está cerrando el socket inmediatamente después de llamar al apagado.

La regla es que en un cierre correcto, ambos lados deben estar al tanto del cierre y haberlo reconocido antes de que alguien realmente cierre el zócalo. Solo encontré referencia para eso en esta página de MSDN , incluso si se cita en esta otra respuesta SO .

Aquí hay una presentación simplificada de lo que se explica mejor si se hace referencia a la página (no sé cómo formatear correctamente las tablas en SO :-():

  • la parte 1 emite el shutdown(socket.SHUT_WR) para notificar que desea finalizar la conexión y continúa leyendo desde el socket
  • la parte 2 recibe la indicación de fin de archivo en el socket (lectura vacía) y aún puede enviar cualquier dato restante; luego llama a su vez el shutdown(socket.SHUT_WR)
  • la parte 1 recibe el final del archivo en el socket y sabe que la otra parte ha terminado usando la conexión
  • ambas partes pueden cerrar el zócalo

Observación: no importa si la parte 2 realmente cierra el socket antes de que la parte 1 recibiera el final del archivo, porque la parte 1 ya solo estaba esperando una indicación de finalización: no se pueden perder datos