Search code examples
pythonsocketstcpconcurrencyconcurrent-programming

Downloading a file in python using sockets TCP


I am writing a TCP concurrent (process based-concurrency) server which accepts a download command. The client should download a file from the server, as of right now I have the filename hard-coded to download in order to test my download algorithm.

I looked up a sample download algorithm and am using the while loop used in that code.

I think my problem is that is that one of the while loops (or maybe both of them) is getting hung up and won't end. I believe that It is the client side, and it is likely waiting for more fileContent.

server

            file = open('download.txt','rb+')
            print "Opened File: " , file.name

            fileContent = file.read(1)
            clientsocket.send(fileContent)
            while (fileContent):
                print "iteration", fileContent
                clientsocket.send(fileContent)
                fileContent = file.read(1)                  
            file.close()

client side

    print "Attempting download..."
    f = open('downloaded.txt' , 'wb+')      
    print "Opened File: " , f.name
    fileContent = s.recv(1)
    while (fileContent):
        print "iteration", fileContent
        f.write(fileContent)
        fileContent = s.recv(1)
    print "Download Complete"
    f.close()

I have accomplished the file transfer without a while loop, using code such as

 f.open(file)
 fContent = f.read(1024)
 client.send(fContent)
 f.close

 f.open(file)
 fContent = server.recv(1024)
 f.write(fContent)
 f.close 

but I know this to cause problems if the file is bigger than the buffer size.

This is a concurrent server that uses an individual process to handle each connection. (I don't believe this should affect my current problem but I am new to concurrency and figured I would mention it.)

Does anyone know why my while loops aren't ending? Or does anyone know of something else I might be doing wrong? Thanks in advance!

edit:

My output:

cli

Attempting download...
Opened File:  downloaded.txt
iteration t
iteration h
iteration i
iteration s
iteration
iteration i
iteration s
iteration
iteration a
iteration
iteration f
iteration i
iteration l
iteration e
iteration

serv

Recived  dl from:  ('127.0.0.1', 38161)  |  2015-12-06 13:07:12.835998
Opened File:  download.txt
iteration t
iteration h
iteration i
iteration s
iteration
iteration i
iteration s
iteration
iteration a
iteration
iteration f
iteration i
iteration l
iteration e
iteration

The client becomes stuck, and I have to ctrl z it out. The server will continue to accept connections. I just realized that I can add a simple print statement after the server's while loop to check if the server's while loop finished.

2nd edit:

The server is not getting hung up (it successfully displays the message after the loop). This leads me to believe that the client is calling recv() and waiting for more fileContent.

3rd edit:

The read/write buffer was only at 1 for testing purposes.


Solution

  • Sending a file byte by byte might be very slow. Best use shutil.copyfileobj, that handles the transfer for you:

    def send_file(socket, filename):
        with open('download.txt','rb') as inp:
            print "Opened File: " , file.name
            out = socket.makefile('wb')
            shutil.copyfileobj(inp, out)
    
    def recv_file(socket, filename):
        with open('download.txt','wb') as out:
            print "Opened File: " , file.name
            inp = socket.makefile('rb')
            shutil.copyfileobj(inp, out)