Home > database >  Python server stop working on client disconnection
Python server stop working on client disconnection

Time:06-21

I'm writing a simple chat program to learn how to use sockets in python. Everything works perfectly, but when a client disconnects, the server stops working: it closes the connections as soon as they send a message, it still accepts connection but when a new connection sends a message it closes it.

Server:

from pickle import TRUE
import socket
import threaded
from threading import Thread
import _thread
import os
import time

#Crating global table for broadcast
global clients
clients = []

#Main
def recive(client):
    global clients
    name = client.recv(2024)
    name = name.decode("utf-8")
    closed = False
    while True:
        #Normal operations
        try:
            string = client.recv(2024)
            string = string.decode("utf-8")
            string = name   ": "   string
            if string == "!exit":
                #client.close()
                print("Connection interrupted")
                closed = True
                break
            else:
                for c in clients:
                    c.send(bytes(string, "utf-8"))
                print(string)
        #Errors or client disconnection handling
        except:
            #client.close()
            print("Connection interrupted")
            break
       
if __name__ == "__main__":
    #Variable assignment
    hostname = socket.gethostname()
    local_ip = socket.gethostbyname(hostname)
    ip = str(local_ip)
    port = 55555

    #Server start
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind((ip, port))
    server.listen()
    print(f"Server listening on {ip} on port {port}")
    #server listening
    while True:
        client, address = server.accept()
        print(f"Connectione estabished - {address[0]}:{address[1]}")
        clients.append(client)
        _thread.start_new_thread(recive ,(client,))

CodePudding user response:

I can't test it but when client disconnects then you have to remove it from list clients.

You don't remove it and when next client connects then server tries to send message to previous client and it may raise error and disconnect new client.


Something like this:

(I uses \n to detect end of message because socket may send many messages as single text)

import socket
from threading import Thread

clients = []

def read(client, buf):
    # every message should ends with '\n`
    while True:
        buf  = client.recv(2024)
        pos = buf.find(b'\n')
        if pos > -1:
            message = buf[:pos].decode("utf-8")
            buf = buf[pos 1:]
            break

    return buf, message

def send(client, message):
    # every message sends with '\n` at the end
    data = (message   '\n').encode('utf-8')
    client.send(data)

def receive(client, address):
    global clients

    buf = b""

    buf, name = read(client, buf)
    print('name:', name)

    while True:
        try:
            buf, message = read(client, buf)
            if message == "!exit":
                print("Connection interrupted")
                break
            else:
                text = f"{name}: {message}"
                print(text)
                for c in clients:
                    send(c, text)
        except Exception as ex:
            print("Exception", ex)
            print("Connection interrupted")
            break

    # --- after looo ---
    #client.close()
    print('remove')
    if client in clients:
        clients.remove(client)

if __name__ == "__main__":
    IP = '0.0.0.0'
    PORT = 55555

    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind((IP, PORT))
    server.listen()
    print(f"Server listening on {IP} on port {PORT}")

    while True:
        client, address = server.accept()
        print(f"Connectione estabished - {address[0]}:{address[1]}")
        clients.append(client)
        Thread(target=receive, args=(client, address)).start()

Client for tests:

import socket

def send(client, message):
    # every message sends with '\n` at the end
    data = (message   '\n').encode('utf-8')
    client.send(data)

client = socket.socket()
client.connect(("0.0.0.0", 55555))
send(client, 'James Bond')
send(client, 'Hello World!')
send(client, 'Bye!')
send(client, '!exit')
client.close()

Maybe it would be better to keep clients in dictionary as {address: connection, ...} because it will be simpler to remove disconected client when there will be more clients.

  • Related