user2957587
user2957587

Reputation: 11

Simple Python Server Client File Transfer

I have this simple python server-client file transfer project going on. There are two parts to each side. First, the client sends a file to server for the first part. Server then appends a line and sends back the file to client in the second part.

My issue is that for some reason, the server code is stuck on receiving whenever I have the return file code in it. If I should comment out the second section of the code, the server receives all the file sent by client. Otherwise it freezes on receiving. And yes, client did send it.

You can ignore all the print commands, just there to see where the problem is.

servercode:

import socket

ssFT = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssFT.bind((socket.gethostname(), 8756))
ssFT.listen(1)
while True:
    (conn, address) = ssFT.accept()
    text_file = 'fileProj.txt'

    #Receive, output and save file
    with open(text_file, "wb") as fw:
        print("Receiving..")
        while True:
            print('receiving')
            data = conn.recv(1024)
            print('Received: ', data.decode('utf-8'))
            if not data:
                print('Breaking from file write')
                break
            fw.write(data)
            print('Wrote to file', data.decode('utf-8'))
        fw.close()
        print("Received..")

    #Append and send file
    print('Opening file ', text_file)
    with open(text_file, 'ab+') as fa:
        print('Opened file')
        print("Appending string to file.")
        string = b"Append this to file."
        fa.write(string)
        fa.seek(0, 0)
        print("Sending file.")
        while True:
            data = fa.read(1024)
            conn.send(data)
            if not data:
                break
        fa.close()
        print("Sent file.")
    break
ssFT.close()

client code:

 import socket

csFT = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
csFT.connect((socket.gethostname(), 8756))

text_file = 'passphrase.txt'

#Send file
with open(text_file, 'rb') as fs: 
    #Using with, no file close is necessary, 
    #with automatically handles file close
    while True:
        data = fs.read(1024)
        print('Sending data', data.decode('utf-8'))
        csFT.send(data)
        print('Sent data', data.decode('utf-8'))
        if not data:
            print('Breaking from sending data')
            break
    fs.close()

#Receive file
print("Receiving..")
with open(text_file, 'wb') as fw:
    while True:
        data = csFT.recv(1024)
        if not data:
            break
        fw.write(data)
    fw.close()
print("Received..")

csFT.close()

Upvotes: 1

Views: 22184

Answers (2)

HUSMEN
HUSMEN

Reputation: 366

The way I solved this same issue is by sending the file size first, then the server can stop waiting as soon as it receives the whole file. I dunno whether there is a better solution or not but this works like a charm:

BUFFER_SIZE = 1024

client.py

import os
fsize = os.path.getsize(text_file)
csFT.send(str(fsize).encode('utf-8'))

with open(text_file, 'rb') as fs:
    data = fs.read(BUFFER_SIZE)
    while data:
        csFT.send(data)
        data = fs.read(BUFFER_SIZE)

server.py

with open(text_file, 'wb') as fw:
    msg = ssFT.recv(BUFFER_SIZE)
    fsize = int(msg.decode('utf-8'))
    rsize = 0

    while True:
        data = ssFT.recv(BUFFER_SIZE)
        rsize = rsize + len(data)
        fw.write(data)
        if  rsize >= fsize:
            print('Breaking from file write')
            break

Upvotes: 0

klassmann
klassmann

Reputation: 528

I tested your code locally with Python 3.

The problem that I saw was with conn.recv in the server code. Because of the conn.recv blocks the connection and it is waiting for more data.

The solution that I found was sending commands to server informing about BEGIN and END of the data transfer, like that:

client.py

#Send file
with open(text_file, 'rb') as fs: 
    #Using with, no file close is necessary, 
    #with automatically handles file close
    csFT.send(b'BEGIN')
    while True:
        data = fs.read(1024)
        print('Sending data', data.decode('utf-8'))
        csFT.send(data)
        print('Sent data', data.decode('utf-8'))
        if not data:
            print('Breaking from sending data')
            break
    csFT.send(b'ENDED') # I used the same size of the BEGIN token
    fs.close()

server.py

with open(text_file, "wb") as fw:
    print("Receiving..")
    while True:
        print('receiving')
        data = conn.recv(32)
        if data == b'BEGIN':
            continue
        elif data == b'ENDED':
            print('Breaking from file write')
            break
        else:
            print('Received: ', data.decode('utf-8'))
            fw.write(data)
            print('Wrote to file', data.decode('utf-8'))
    fw.close()
    print("Received..")

Client.py complete code: https://pastebin.com/LySsgEe4

Server.py complete code: https://pastebin.com/KADZpqkM

I hope to help!

Upvotes: 3

Related Questions