import socket
import os
import struct
import traceback

def send_one_message(sock, data):
    length = len(data)
    sock.sendall(struct.pack('!I', length))
    sock.sendall(data)

def recv_one_message(sock):
    lengthbuf = recvall(sock, 4)
    length, = struct.unpack('!I', lengthbuf)
    return recvall(sock, length)

def recvall(sock, count):
    fragments = []
    while count: 
        chunk = sock.recv(count)
        if not chunk: 
            return None
        fragments.append(chunk)
        count -=len(chunk)
    arr = b''.join(fragments)
    return arr

def main():
    host = 'tp-1a260-20.enst.fr' # replace with the server IP address or hostname
    port = 65122 # replace with the server port number

    try:
        client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        client_socket.connect((host, port))

        # send "Hello"
        message = 'Hello'
        send_one_message(client_socket,message.encode())
        response = recv_one_message(client_socket).decode()
        print(f'Received response: {response}')

        # send file
        filename = 'example.txt'
        filesize = os.path.getsize(filename)
        message = 'file'
        send_one_message(client_socket,message.encode())
        send_one_message(client_socket,filename.encode())
        send_one_message(client_socket,str(filesize).encode())
        with open(filename, 'rb') as f:
            data = f.read(1024)
            while data:
                send_one_message(client_socket,data)
                data = f.read(1024)
        response = recv_one_message(client_socket).decode()
        print(f'Received response: {response}')

        # send "Bye"
        message = 'Bye'
        send_one_message(client_socket,message.encode())

        client_socket.close()
    except Exception as e:
        print(f'Error : {e}')
        traceback.print_exc()

if __name__ == '__main__':
    main()