Python Socket - Can't connect a second time

1.7k views Asked by At

I have set up a socket server with a client and a host. It works fine until the client has disconnected, with both .shutdown() and .close(). When I then launch the client again, it can't connect. I presume this is not because of how I've written my code but rather what I haven't written.

How do I make the server truly disconnect the client's connection so that it can connect again?

Server:

import socket, threading, time, json

ONLINE_USERS = []
SESSION = None

class User():
    def __init__(user, connection, address):
        print('for', address, '{Connection established}')
        user.connection = connection
        user.address = address
        user.character = None
        threading.Thread(target=user.process, args=(), daemon=True).start()

    def process(user):
        time.sleep(1)

        user.send("&pLogin\n^^^^^\n")
        username = user.send("&iUser>")
        password = user.send("&iPass>")
        print(user.ping())
        print(user.logout())

    def send(user, *x):
        user.connection.sendall(str.encode(str(x)))
        data = user.connection.recv(1024)
        return data if data!=b'\x01' else True

    def recv(user, x):
        user.connection.recv(x)

    def ping(user):
        start = time.time()
        user.connection.sendall(b'\x02')
        end = float(user.connection.recv(1024))
        return round((end - start) * 1000)

    def logout(user):
        user.connection.sendall(b'\x04')
        return user.connection.recv(4)


class Session():
    def __init__(session, host='', port=12345):
        session.host = host
        session.port = port
        session.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        session.socket.bind((host, port))
        session.socket.listen(10)

        def accept():
            conn = User(*session.socket.accept())
        session.thread_accept = threading.Thread(target=accept, args=(), daemon=True).start()

    def shutdown():
        for user in ONLINE_USERS.keys():
            ONLINE_USERS[user].connection.sendall(bytes([0xF]))


if __name__ == '__main__':
    SESSION = Session()
    input('Press heart to continue!\n')

Client:

import socket, sys, threading, time, os


def clear(t=0.5):
    time.sleep(t)
    os.system('cls')

def tryeval(x, default):
    try:
        return eval(x)
    except:
        return default


class Client():
    def __init__(client):
        try:
            server_info = input('IP_ADDRESS:PORT>').split(':')
            client.host = server_info[0]
            client.port = int(server_info[1])
        except:
            client.host = 'localhost'
            client.port = 12345

        client.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        client.socket.settimeout(10)

        try:
            client.socket.connect((client.host, client.port))
            clear()
            client.data_exchange()

        finally:
            client.shutdown()

    def data_exchange(client):
        while True:
            data = client.socket.recv(1024)

            if data:
                if data==b'\x02':
                    client.socket.sendall(str.encode(str(time.time())))
                elif data==b'\x04':
                    client.shutdown()

                else:
                    data = tryeval(data, ())
                    response = []

                    for item in data:
                        try:
                            prefix, content = item[:2], item[2:]
                            if prefix=='&p':
                                print(content, end='')
                            elif prefix=='&i':
                                response.append(input(content))
                            if prefix=='&c':
                                time.sleep(float(content))
                                clear()
                        except:
                            pass

                    if len(response)>0:
                        client.socket.sendall(str.encode(str(tuple(response))))
                    else:
                        client.socket.sendall(b'\x01')


            time.sleep(0.001)

    def shutdown(client):
        try:
            client.socket.sendall(b'\x04')
        except:
            pass
        print('Shutting down program.')
        client.socket.shutdown(socket.SHUT_RDWR)
        print('Socket has been shutdown.')
        client.socket.close()
        print('Socket has been closed.')
        print('Exiting program')
        time.sleep(1)
        sys.exit()




if __name__ == '__main__':
    client = Client()
1

There are 1 answers

1
Armali On

"The server repeatedly calls accept waiting for new incoming connections." No it doesn't. It calls accept once in a thread...which exits. – Mark Tolonen