Envío de un archivo a través de sockets TCP en Python


He podido copiar con éxito el contenido del archivo (imagen) a un nuevo archivo. Sin embargo, cuando intento lo mismo sobre sockets TCP me enfrento a problemas. El bucle del servidor no está saliendo. El bucle cliente sale cuando llega al EOF, sin embargo el servidor no puede reconocer EOF.

Aquí está el código:

Servidor

import socket               # Import socket module

s = socket.socket()         # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345                 # Reserve a port for your service.
s.bind((host, port))        # Bind to the port
f = open('torecv.png','wb')
s.listen(5)                 # Now wait for client connection.
while True:
    c, addr = s.accept()     # Establish connection with client.
    print 'Got connection from', addr
    print "Receiving..."
    l = c.recv(1024)
    while (l):
        print "Receiving..."
        f.write(l)
        l = c.recv(1024)
    f.close()
    print "Done Receiving"
    c.send('Thank you for connecting')
    c.close()                # Close the connection

Cliente

import socket               # Import socket module

s = socket.socket()         # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345                 # Reserve a port for your service.

s.connect((host, port))
s.send("Hello server!")
f = open('tosend.png','rb')
print 'Sending...'
l = f.read(1024)
while (l):
    print 'Sending...'
    s.send(l)
    l = f.read(1024)
f.close()
print "Done Sending"
print s.recv(1024)
s.close                     # Close the socket when done

Aquí está el captura de pantalla:

Servidor Servidor

Cliente Cliente

Editar 1: Datos extra copiados. Hacer que el archivo " no esté completo." La primera columna muestra la imagen que se ha recibido. Parece ser más grande que el enviado. Debido a esto, no soy capaz de abrir la imagen. Parece un archivo dañado.

Tamaños de archivo

Edit 2: Así es como lo hago en la consola. Los tamaños de archivo son los mismos aquí. Consola PythonLos mismos tamaños de archivo

Author: Swaathi Kakarla, 2014-12-02

5 answers

El cliente debe notificar que terminó de enviar, utilizando socket.shutdown (no socket.close que cierra tanto la parte de lectura / escritura del zócalo):

...
print "Done Sending"
s.shutdown(socket.SHUT_WR)
print s.recv(1024)
s.close()

UPDATE

El cliente envía Hello server! al servidor; que se escribe en el archivo en el lado del servidor.

s.send("Hello server!")

Retire la línea anterior para evitarlo.

 23
Author: falsetru,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-02 05:22:57

Eliminar el código siguiente

s.send("Hello server!")

Porque su envío s.send("Hello server!") al servidor, por lo que su archivo de salida es algo más de tamaño.

 6
Author: Rama Krishna,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-26 12:27:24

El problema es extra 13 bytes que server.py recibe en la salida. Para resolver eso escriba" l = c. recv(1024) " dos veces antes del bucle while como se muestra a continuación.

print "Receiving..."
l = c.recv(1024) #this receives 13 bytes which is corrupting the data
l = c.recv(1024) # Now actual data starts receiving
while (l):

Esto resuelve el problema, probado con diferentes formatos y tamaños de archivos. Si alguien sabe a qué se refiere este inicio de 13 bytes, por favor responda.

 0
Author: gajendra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-03 19:34:51

Poner el archivo dentro de while True así

while True:
     f = open('torecv.png','wb')
     c, addr = s.accept()     # Establish connection with client.
     print 'Got connection from', addr
     print "Receiving..."
     l = c.recv(1024)
     while (l):
         print "Receiving..."
         f.write(l)
         l = c.recv(1024)
     f.close()
     print "Done Receiving"
     c.send('Thank you for connecting')
     c.close()   
 0
Author: Irviano Yoe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-13 16:59:57

Puede cambiar la condición de su bucle de acuerdo con el siguiente código, cuando la longitud de l es menor que el tamaño del búfer, significa que alcanzó el final del archivo

while (True):
    print "Receiving..."
    l = c.recv(1024)        
    f.write(l)
    if len(l) < 1024:
        break
 0
Author: danitiger33,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-12 13:20:12