0

I'm working on a client server script in python to transfer a file over a socket connection. The file transfer works successfully, however on the client.py, it doesn't seem to break out of the while True loop when there's no bytes_read from the socket so the program cannot continue to to run print(f"[INFO] File data has been received").

Here's what it looks like:

server.py

import socket
import threading

SERVER_PORT = 8081
TEXT_FORMAT = 'utf-8'
CHUNK_SIZE = 1024
FILE_NAME = "files_server/text"

server = socket.socket()
server.bind(('',SERVER_PORT))

def handle_client(client_connected, client_address, file_name):
    # STEP 1 & 2 - Advising client of file size and file extension:
    file_size = str(os.path.getsize(file_name)).encode()
    client_connected.send(file_size)
    file_extension = str(file_name.split(".")[-1]).encode()
    client_connected.send(file_extension)

    # STEP 3 - Sending file to the client:
    with open(file_name, 'rb') as file:
        while True:
            # Read bytes by selected CHUNK Size
            bytes_to_send = file.read(CHUNK_SIZE)
            if not bytes_to_send:
                # No more to send, file transmission completed
                break
            # Send chunk:
            client_connected.sendall(bytes_to_send)
        print('[FILE SENT SUCCESSFULLY]')
    print(f"[CLOSING CONNECTION] Closing connection with {client_address}. Total Connections {threading.active_count() -1}")

def start():
    server.listen(0)
    print(f"[LISTENING] Server is listening on port {SERVER_PORT}")

    # Accept new connections:
    while True:
        client_connected, client_address = server.accept()
        print(f"[NEW CONNECTION] Connected with {client_address}. Total Connections {threading.active_count()}")
        thread = threading.Thread(target=handle_client(client_connected,client_address,FILE_NAME))
        thread.start()

start()

client.py

import socket
import datetime
import re
from tqdm import tqdm

SERVER_HOST = 'localhost'
SERVER_PORT = 8081
TEXT_FORMAT = 'utf-8'
CHUNK_SIZE = 1024


def bytes_to_human_readable(size_bytes):
    if size_bytes == 0:
        return "0B"
    size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
    i = int(math.floor(math.log(size_bytes, 1024)))
    p = math.pow(1024, i)
    s = round(size_bytes / p, 2)
    return "%s %s" % (s, size_name[i])


client = ""
# Connecting to server:
try:
    print(f"[STATUS] Connecting to {SERVER_HOST}:{SERVER_PORT}...")
    client = socket.socket(socket.AF_INET,
                           socket.SOCK_STREAM)

    client.connect((SERVER_HOST, SERVER_PORT))
    print(f"[STATUS] Connected to {SERVER_HOST}:{SERVER_PORT} successfully")
except:
    print("Failed to connect to server")

# STEP 1 - Receiving file size from server:
file_size_and_extension = client.recv(10).decode()
# file_size = bytes_to_human_readable(int(file_size))
array_file_size_and_extension = re.split('(\d+)',file_size_and_extension)
file_size = array_file_size_and_extension[1]
file_extension = array_file_size_and_extension[2]
print(f"[INFO] File size is {file_size} and extension is {file_extension}")

# STEP 3 - Downloading file:
currentDT = datetime.datetime.now()
file_name = 'files_client/' + currentDT.strftime("%Y-%m-%d %H:%M:%S")

progress = tqdm(range(int(file_size)), f"Receiving {file_name}", unit="B", unit_scale=True, unit_divisor=CHUNK_SIZE)
with open(file_name, "wb") as file:
    while True:
        # Read chunk size from socket
        bytes_read = client.recv(CHUNK_SIZE)
        if not bytes_read:
            # Nothing has been received, file transmission is complete
            break
        file.write(bytes_read)
        progress.update(len(bytes_read))

progress.close()
print(f"[INFO] File data has been received")
client.close()

  • 1
    Unless I am mistaken, you claim loud `"[CLOSING CONNECTION]...` but never actually close it in server code. – Serge Ballesta Dec 23 '21 at 14:32
  • just find something to put in the while rather doing it with `if brake` why not `while bytes_read:`? or even use `do ... while` – Alone Bashan Dec 23 '21 at 14:33
  • @SergeBallesta that was exactly why I couldn't break out of the loop, I needed to close the connection on the server! Thank you so much for your help. I'm new to Python and Socket connections. That's all that was needed. – Matthew Jones Dec 23 '21 at 14:43
  • `client.recv(10).decode()` 99.9% of the time I see a line like this it's a bug, including this one. You can't assume that what the server sends in a single `send` will be returned in a single `recv`. See [this answer](https://stackoverflow.com/a/43420503/238704) for more details. Also, if you're not checking the return value of `send`, and you're not in this code, then use `sendall` instead. – President James K. Polk Dec 23 '21 at 15:07

0 Answers0