socket real online example español all python sockets tcp port

real - Python: Encuadernación socket: "Dirección ya en uso"



socket python 3 español (12)

Aquí está el código completo que he probado y absolutamente NO me da un error de "dirección que ya está en uso". Puede guardar esto en un archivo y ejecutar el archivo desde el directorio base de los archivos HTML que desea publicar. Además, puede cambiar directorios mediante programación antes de iniciar el servidor

import socket import SimpleHTTPServer import SocketServer # import os # uncomment if you want to change directories within the program PORT = 8000 # Absolutely essential! This ensures that socket resuse is setup BEFORE # it is bound. Will avoid the TIME_WAIT issue class MyTCPServer(SocketServer.TCPServer): def server_bind(self): self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.socket.bind(self.server_address) Handler = SimpleHTTPServer.SimpleHTTPRequestHandler httpd = MyTCPServer(("", PORT), Handler) # os.chdir("/My/Webpages/Live/here.html") httpd.serve_forever() # httpd.shutdown() # If you want to programmatically shut off the server

Tengo una pregunta sobre el socket del cliente en la red TCP / IP. Digamos que uso

try: comSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) comSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) except socket.error, msg: sys.stderr.write("[ERROR] %s/n" % msg[1]) sys.exit(1) try: comSocket.bind(('''', 5555)) comSocket.connect() except socket.error, msg: sys.stderr.write("[ERROR] %s/n" % msg[1]) sys.exit(2)

El socket creado estará vinculado al puerto 5555. El problema es que después de finalizar la conexión

comSocket.shutdown(1) comSocket.close()

Usando wireshark, veo el socket cerrado con FIN, ACK y ACK desde ambos lados, no puedo usar el puerto nuevamente. Obtuve el siguiente error:

[ERROR] Address already in use

Me pregunto cómo puedo limpiar el puerto de inmediato para que la próxima vez aún pueda usar ese mismo puerto.

comSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

setsockopt no parece poder resolver el problema ¡Gracias!


Como mencionó Felipe Cruze, debes establecer SO_REUSEADDR antes de enlazar. Encontré una solución en otro sitio: solución en otro sitio, reproducida a continuación

El problema es que la opción de socket SO_REUSEADDR debe establecerse antes de que la dirección se vincule al socket. Esto se puede hacer subclasificando ThreadingTCPServer y anulando el método server_bind de la siguiente manera:

import SocketServer, socket class MyThreadingTCPServer(SocketServer.ThreadingTCPServer): def server_bind(self): self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.socket.bind(self.server_address)


Creo que la mejor manera es simplemente matar el proceso en ese puerto, escribiendo en el fuser -k [PORT NUMBER]/tcp del terminal fuser -k [PORT NUMBER]/tcp , por ejemplo fuser -k 5001/tcp .


Debe establecer allow_reuse_address antes del enlace. En lugar de SimpleHTTPServer, ejecute este fragmento:

Handler = SimpleHTTPServer.SimpleHTTPRequestHandler httpd = SocketServer.TCPServer(("", PORT), Handler, bind_and_activate=False) httpd.allow_reuse_address = True httpd.server_bind() httpd.server_activate() httpd.serve_forever()

Esto evita que el servidor se enlace antes de que tengamos la oportunidad de establecer las banderas.



En realidad, el indicador SO_REUSEADDR puede tener consecuencias mucho mayores: SO_REUSADDR le permite usar un puerto que está atascado en TIME_WAIT, pero aún no puede usar ese puerto para establecer una conexión con el último lugar al que se conectó. ¿Qué? Supongamos que escojo el puerto local 1010 y me conecto al puerto 300 de foobar.com y luego me cierro localmente, dejando ese puerto en TIME_WAIT. Puedo reutilizar el puerto local 1010 de inmediato para conectarme a cualquier lugar, excepto al puerto 300 de foobar.com.

Sin embargo, puede evitar por completo el estado TIME_WAIT asegurándose de que el extremo remoto inicie el cierre (evento de cierre). Por lo tanto, el servidor puede evitar problemas al permitir que el cliente cierre primero. El protocolo de la aplicación debe estar diseñado para que el cliente sepa cuándo cerrar. El servidor puede cerrarse de forma segura en respuesta a un EOF del cliente, sin embargo, también deberá establecer un tiempo de espera cuando se espera un EOF en caso de que el cliente haya abandonado la red de forma descortés. En muchos casos, simplemente esperar unos segundos antes de que el servidor se cierre será suficiente.

También te aconsejo que aprendas más sobre redes y programación de redes. Ahora debería al menos cómo funciona el protocolo tcp. El protocolo es bastante trivial y pequeño y, por lo tanto, puede ahorrarle mucho tiempo en el futuro.

Con el comando netstat , puede ver fácilmente qué programas ((nombre_programa, pid) tuple) están vinculados a qué puertos y cuál es el estado actual del socket: TIME_WAIT, CLOSING, FIN_WAIT, etc.

Se puede encontrar una muy buena explicación de las configuraciones de red de Linux https://serverfault.com/questions/212093/how-to-reduce-number-of-sockets-in-time-wait .


Encontré otra razón para esta excepción. Cuando ejecuté la aplicación desde Spyder IDE (en mi caso fue Spyder3 en Raspbian) y el programa terminó con ^ C o una excepción, el socket aún estaba activo:

sudo netstat -ap | grep 31416 tcp 0 0 0.0.0.0:31416 0.0.0.0:* LISTEN 13210/python3

Al ejecutar nuevamente el programa, se encontró la "Dirección ya en uso"; el IDE parece comenzar la nueva ''ejecución'' como un proceso separado que encuentra el socket utilizado por la ''ejecución'' previa.

socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

no ayudó.

Proceso de asesinato 13210 ayudado. Iniciando el script de python desde la línea de comandos como

python3 <app-name>.py

siempre funcionó bien cuando SO_REUSEADDR se estableció en verdadero. El nuevo IDE Thonny IDE o Idle3 no tenía este problema.


Intente utilizar la SO_REUSEADDR socket SO_REUSEADDR antes de enlazar el socket.

comSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

Editar: Veo que todavía tienes problemas con esto. Hay un caso donde SO_REUSEADDR no funcionará. Si intenta vincular un socket y volver a conectarse al mismo destino (con SO_REUSEADDR habilitado), entonces TIME_WAIT seguirá en vigor. Sin embargo, le permitirá conectarse a un host diferente: puerto.

Un par de soluciones vienen a la mente. Puede continuar reintentando hasta que pueda obtener una conexión nuevamente. O si el cliente inicia el cierre del socket (no del servidor), entonces debería funcionar mágicamente.


Otra solución, en el entorno de desarrollo, por supuesto, es matar el proceso de usarlo, por ejemplo

def serve(): server = HTTPServer(('''', PORT_NUMBER), BaseHTTPRequestHandler) print ''Started httpserver on port '' , PORT_NUMBER server.serve_forever() try: serve() except Exception, e: print "probably port is used. killing processes using given port %d, %s"%(PORT_NUMBER,e) os.system("xterm -e ''sudo fuser -kuv %d/tcp''" % PORT_NUMBER) serve() raise e


Para mí, la mejor solución fue la siguiente. Como la iniciativa de cerrar la conexión fue realizada por el servidor, setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) no tuvo efecto y TIME_WAIT estaba evitando una nueva conexión en el mismo puerto con error:

[Errno 10048]: Address already in use. Only one usage of each socket address (protocol/IP address/port) is normally permitted

Finalmente utilicé la solución para permitir que el sistema operativo elija el puerto en sí, luego se usa otro puerto si el precedente aún está en TIME_WAIT.

He reemplazado:

self._socket.bind((guest, port))

con:

self._socket.bind((guest, 0))

Como se indicó en la documentación del socket python de una dirección tcp:

Si se proporciona, source_address debe ser un 2-tuple (host, puerto) para que el socket se vincule como su dirección fuente antes de conectarse. Si el host o el puerto son '''' o 0 respectivamente, se usará el comportamiento predeterminado del sistema operativo.


Sé que ya has aceptado una respuesta, pero creo que el problema tiene que ver con llamar a bind () en un socket de cliente. Esto podría estar bien, pero bind () y shutdown () no parecen funcionar bien juntos. Además, SO_REUSEADDR se usa generalmente con conectores de escucha. es decir, en el lado del servidor.

Deberías estar pasando e ip / port para conectarte (). Me gusta esto:

comSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) comSocket.connect(('''', 5555))

No llame a bind (), no configure SO_REUSEADDR.


socket.socket() debería ejecutarse antes de socket.bind() y usar REUSEADDR como se dijo