Python Forum
Client/Server proper finalizing transfer - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: Networking (https://python-forum.io/forum-12.html)
+--- Thread: Client/Server proper finalizing transfer (/thread-37643.html)



Client/Server proper finalizing transfer - wolfman5874 - Jul-04-2022

Hi all. Been learning python for a couple months now and started getting into sockets the past few days. I have a simple client/server app that will just transfer files between the two. As of right now I have only coded the section of the app where the client will make a request for a file and the server will send the file to the client. The file transfer works as expected but after the file transfers successfully the client hangs. I'm assuming it's stuck still waiting for more data. I send the file size first to the client so it knows how big of a file to expect and use it in the recv loop. I can close the connection or shutdown but I want the connection to stay open in case I want to download more files. I print the file size on both the server side and client side to make sure the sizes match and they do so I'm not exactly sure how to finalize this transaction without breaking the connection. As of the right I'm just focuses on sending the node.msi file. Any help would be appreciate.

server:

import socket
import threading
import os
import time

BYTE_SIZE       =64
HOST            =socket.gethostname()
SERVER          =socket.gethostbyname(HOST)
PORT            =5050
ADDR            =(SERVER,PORT)
FORMAT          ='utf-8'
DISCO_MSG       ="d" 

server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(ADDR)

def client_requests(conn,addr):
    print(f"[NEW CONNECTION] {addr} connected.")

    connected = True
    while connected:
        request = conn.recv(1024).decode(FORMAT)
        if request:
            file_name = request
            if file_name == "node":
                file_size = os.path.getsize("node.msi")
                print("file size to send: ", file_size)
                conn.send(str(file_size).encode(FORMAT))

                with open("node.msi", "rb") as file:
                    c = 0
                    start_time = time.time()
                    while c <= file_size:
                        data = file.read(1024)
                        if not data:
                            end_time = time.time()
                            print("send time: ", end_time - start_time)
                            file.close()
                            break
                        conn.send(data)
                        c = c + len(data)
                    
            if file_name == "postman":
                file_size = os.path.getsize("postman.exe")
                print(file_size)

        if request == DISCO_MSG:
            conn.send("disconnected from server".encode(FORMAT))
            conn.close()
            print(f"[CLIENT DISCONNECTED] {addr} disconnected")
            break        
    
def start_server():
    server.listen()
    print(f"[SERVER] running / listening on {ADDR}")
    while True:
        conn, addr = server.accept()
        thread = threading.Thread(target=client_requests,args=(conn,addr))
        thread.start()
        print(f"[ACTIVE CONNECTIONS] {threading.active_count() - 1}")

start_server()
client:

import socket
import time

BYTE_SIZE       =64
FORMAT          ='utf-8'
SERVER          ='192.168.0.77'
PORT            =5050
ADDR            =(SERVER,PORT)


########## SERVER CONNECT LOOP #######
attempt = 0
while attempt < 10:  
    try:
        print("attempting to connect to server...")
        client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        client_socket.connect(ADDR)
        break
    except:
        attempt += 1
        print("attempt " + str(attempt) +"/10 failed")
        time.sleep(.5)

        if attempt == 10:
            print("unable to connect to server, terminating program")
            time.sleep(.5)
            exit()
    
   
########### MAIN PROGRAM  ################
cmd = True
while cmd:
    print("================================")
    time.sleep(.3)
    print("||       Integrity            ||")
    time.sleep(.3)
    print("||        1. FT               ||")
    time.sleep(.3)
    print("||============================||")
    time.sleep(.3)
    print("     connected to: " + SERVER)

    cmd = input("MAIN CMD: ")

   ######## FILE MANAGEMENT ################    
        

    if cmd == "1":
        file_transfer_program = True
        while file_transfer_program:
            def download_file(file_name):
                file_name = str(file_name).encode(FORMAT)
                client_socket.sendall(file_name)

                file_size = client_socket.recv(100).decode(FORMAT)
                print("file size to receive: ", file_size)
                
                with open("./recv/" + "node.msi", "wb") as file:
                    c = 0
                    start_time = time.time()
                    while c <= int(file_size):
                        data = client_socket.recv(1024)
                        if not data:
                            file.close()
                            end_time = time.time()
                            print("download time: ", end_time - start_time)
                            break
                        file.write(data)
                        c = c + len(data)

            print("############ FILE TRANSFER ##################")
            print(" ########### 1. download file #############")
            print(" ########### 2. send file #########")
            
            ft_cmd = input("ft_cmd: ")

            if ft_cmd == "1":
                file_to_download = input("enter file_name: ")
                download_file(file_to_download)
                
            if ft_cmd == "2":
                print('option not available atm')

            if ft_cmd == "":
                break

            elif ft_cmd == "x":
                break


############## END CONN ##########################

    elif cmd == "d":
        discomsg = cmd
        encoded_discomsg = discomsg.encode(FORMAT)
        encoded_discomsg_len = len(encoded_discomsg)
        str_encoded_msg_len = str(encoded_discomsg_len).encode(FORMAT)
        str_encoded_msg_len += b' ' * (BYTE_SIZE - len(str_encoded_msg_len))

        client_socket.send(str_encoded_msg_len)
        client_socket.send(encoded_discomsg)
            
        print(client_socket.recv(2048).decode(FORMAT))
        
        break

    elif cmd == '':
        discomsg = "d"
        encoded_discomsg = discomsg.encode(FORMAT)
        encoded_discomsg_len = len(encoded_discomsg)
        str_encoded_msg_len = str(encoded_discomsg_len).encode(FORMAT)
        str_encoded_msg_len += b' ' * (BYTE_SIZE - len(str_encoded_msg_len))

        client_socket.send(str_encoded_msg_len)
        client_socket.send(encoded_discomsg)
            
        print(client_socket.recv(2048).decode(FORMAT))
        
        break

    else:
        print("not an option")



RE: Client/Server proper finalizing transfer - wolfman5874 - Jul-04-2022

ahhhhh I figured it out. I took out the "if not data" statement and replaced it with "if c == file_size" and it breaks successfully without breaking the connection.


server:

with open("node.msi", "rb") as file:
                    c = 0
                    start_time = time.time()
                    while c <= file_size:
                        data = file.read(1024)
                        conn.send(data)
                        c = c + len(data)
                        if c == file_size:
                            end_time = time.time()
                            print("send time: ", end_time - start_time)
                            file.close()
                            break
client:

with open("./recv/" + "node.msi", "wb") as file:
                    c = 0
                    start_time = time.time()
                    while c <= int(file_size):
                        data = client_socket.recv(1024)
                        file.write(data)
                        c = c + len(data)
                        if c == int(file_size):
                            file.close()
                            end_time = time.time()
                            print("download time: ", end_time - start_time)
                            break