Home > Mobile >  python socket - how to complete/close the connection on the client side?
python socket - how to complete/close the connection on the client side?

Time:10-09

server.py:

json files from NVD are used here

import socket, json, random, threading, zipfile, requests, re, zipfile
from bs4 import BeautifulSoup
from zipfile import *
      

def listen_user(user):
    for x in range(2018,2021,1):
        filename = "nvdcve-1.1-"   str(x)   ".json"
        print(filename)
        with open(filename, 'rb') as file:
            sendfile = file.read()
        user.sendall(sendfile)
        print('file sent'   str(x))

def start_server():
    while True:
        user_socket, address = server.accept()
        print(f"User <{address[0]}> connected!")

        users.append(user_socket)
        listen_accepted_user = threading.Thread(
            target=listen_user,
            args=(user_socket,)
        )

        listen_accepted_user.start()

if __name__ == '__main__':
    users = []
    server = socket.socket(
        socket.AF_INET,
        socket.SOCK_STREAM,
    )

    server.bind(
        ("127.0.0.1", 100)
    )

    server.listen(5)
    print('waiting for connection...')
    start_server()

client.py

import socket, json, random
from threading import Thread

def start_client(client):
    savefilename = str(random.randint(1,10))   'new.json'
    print(savefilename)
    with client,open(savefilename,'wb') as file:
        while True:
            recvfile = client.recv(4096)
            if not recvfile:
                print('1 client')
                break
            file.write(recvfile)
    file.close()
    print('2 client')
    client.close()


if __name__ == '__main__':
    client = socket.socket(
        socket.AF_INET,
        socket.SOCK_STREAM,
    )
    client.connect(
        ("127.0.0.1", 100)
    )
    start_client(client)

when I send files - they are sent almost in full, but the program does not reach the line "print ('1 client')" or "print ('2 client')"

and the *new file contains all lines except a few dozen of the last

please help - how to fix the code?

CodePudding user response:

recvfile = client.recv(4096) is inside the while loop and it is continuously waiting for the next bytes to receive. The client doesn't know the files are sent, so it waits for the next 4096 bytes and doesn't exit the loop.

To let the client know that the file transfer is completed, you can send a message from the server.py which you can validate in the client and break the loop as shown below.

server.py

def listen_user(user):
    for x in ["f.json","g.json"]:
        filename = x
        print(filename)
        with open(filename, 'rb') as file:
            sendfile = file.read()
        user.sendall(sendfile)
        print('file sent'   str(x))
    user.send(b"Done")

Client.py

def start_client(client):
    savefilename = str(random.randint(1,10))   'new.json'
    print(savefilename)
    with client,open(savefilename,'wb') as file:
        while True:
            recvfile = client.recv(4096)
            if recvfile.decode("utf-8") =="Done":
                print('1 client')
                file.close()
                break
            file.write(recvfile)
    print('2 client')
    client.close()

CodePudding user response:

The call client.recv(4096) means that you are waiting for 4096 bytes to be received, then doing something with those bytes. What's likely happening in this case is that you're writing out all of the bytes, minus those that don't quite fill up the buffer at the end. This leaves the client waiting with a buffer with space that is doesn't think it is ready to write out yet.

I'm guessing that you're assuming that client.recv() will return an empty string once you've gotten all the data; this is not the case based on your code. If you want the client to be able to terminate the connection, you're going to need to send some kind of control sequence or try to otherwise assess the bytes received from the server to determined when it's time to close the connection. If you do this, you will probably want to set bufsize when calling client.recv() to 1, and instead use some other method to buffer before you write to a file.

For instance, since you're sending JSON data, you could concatenate the bytes to a variable and then repeatedly try to parse JSON. Once you have managed to successfully parse JSON, you can terminate the connection on the client side (though this would mean you have to open a new connection per file you're sending).

However, that raises the question: why do you need to close from the client side? Usually the server will just close the connection once it is done sending all of the relevant data.

  • Related