0

I'm trying to run a client/server script, where the client sends a file to the server and waits for responses until the server sends a stop message. The problem is: once the connection is established the client starts sending data but until I press CTRL-C the server cannot recreate the file. Only after CTRL-C print "file is fully created" and the file becomes visible, instead, before it's seems to be waiting for something. idk where the problem is. Also tried changing condition on send loop using len(), but doesn't work. Anyone know how to fix it ?

client.py :

import socket               # Import socket module
# from threading import Thread

s = socket.socket()         # Create a socket object
HOST = "101.xx.x.xxx"       # public IP address
PORT = 4243                 # Reserve a port for your service.
PDF_PATH = "exam.pdf"
s.connect((HOST, PORT))

def send():
    f = open(PDF_PATH, "rb")
    while data := f.read(4096):
        s.send(data)
    f.close()
    return
    
def receive():
    while 1:
        exercise = s.recv(4096)
        if exercise == "stop!":
            s.close()
            break
        f = open(f"{exercise}.txt", "wb")
        while data := f.read(4096):
            f.write(data)
    return

def main():
    send()
    receive()
    
if __name__ == "__main__":
    main()

server.py :

import socket
from threading import Thread

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
HOST = socket.gethostname()
IP = socket.gethostbyname(HOST)
PORT = 4243
s.bind(('', PORT))
s.listen(5)

def receive_file(conn, i):
    f = open(f"exam.pdf", "wb")
    while received := conn.recv(4096):
        f.write(received)
    print("File is fully copied\n")
    f.close()

def send_result(conn,i):
    while 1:
        nbr = str(input("which exercise? "))
        if nbr == "stop!":
            break
        f = open(f"exercise{nbr}.txt", "rb")
        conn.send(bytes(f"exercise{nbr}.txt", encoding="utf-8"))
        while data := f.read(4096):
            conn.send(data)
        f.close()

def main():
    try:
        while 1:
            i = 0
            conn, addr = s.accept()
            print("Got connection from", addr)
            # c.send(b"Thank you for connecting")
            t = Thread(target=receive_file, args=(conn, i))
            t.start()
            t.join()
            t = Thread(target=send_result, args=(conn, i))
            t.start()
            t.join()
    except KeyboardInterrupt:
        print("interrupting \n")
        conn.close()
        s.close()


if _name_ == '_main_':
    main()
2
  • if exercise == "stop!": exercise is a bytes object and thus can never be equal to "stop!" which is a string. Commented Jun 23, 2022 at 13:44
  • yes I forgot .decode() after exercise, but problem there is no there. I solved as @Mark Tolonen said. Commented Jun 23, 2022 at 15:26

1 Answer 1

1

conn.recv() in the server won't return '' (no more data) unless the client closes the connection or calls shutdown(SHUT_WR) to indicate sends are complete:

def send():
    with open(PDF_PATH, "rb") as f:
        while data := f.read(4096):
            s.sendall(data)
        s.shutdown(socket.SHUT_WR)

An alternative is to design a protocol that sends the length of data before the data so you know when you've received the complete transmission. This would be required if you need to send more than one thing without closing the socket or shutting down sends. You're going to need this to make the receive portion of the server work if you want to send more than one exercise file.

Refer to this answer for an example of sending multiple files over a socket.

Sign up to request clarification or add additional context in comments.

1 Comment

thanks a lot mark, it works fine for only one file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.