argillander
argillander

Reputation: 43

Socket.sendall() not sending to all connected clients

I'm struggling with the .sendall() method for a client/server -setup. Several clients can connect individually and send messages to the server and get the echoed response. However, I expect the messages sent to show up for all the connected clients in a chat-like Environment.

This is the code running on the server application.

def clientHandler(conn, addr):
    name = addr[0]
    print(addr, " connected to the server")
    while True:
        data = conn.recv(1024)
        if tostr(data)[0:5] == '/name':
            print('setting name')
            setname(data)
        if not data:
            break
        conn.sendall(str.encode(checkname(addr[0]) + tostr(data)))
        print('Received Message: ', tostr(data))


HOST = '' #LOCALHOST
PORT = 1400

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((HOST, PORT))
sock.listen(999999)

print('Server is running' + '-'*10)

for i in range(999999):
    conn, addr = sock.accept()
    Thread(target = clientHandler, args = (conn, addr)).start()

sock.close()

Thank you in advance

Upvotes: 1

Views: 2027

Answers (1)

Alex Martelli
Alex Martelli

Reputation: 881843

As I had originally said in a comment (but now decided is better said in an answer), sendall sends all bytes to a single connection. You need to add something like:

lock = threading.Lock()
all_clients = []

at the top; in the main loop, where you now have just conn, addr = sock.accept(), have

conn, addr = sock.accept()
with lock:
    all_clients.append(conn)

In clientHandler, where you now have just conn.sendall(str.encode(checkname(addr[0]) + tostr(data))), have instead

with lock:
    for c in all_clients:
        c.sendall(str.encode(checkname(addr[0]) + tostr(data)))

IOW, you need to explicitly code the "broadcast" business logic in your server -- it's absolutely not implicit in sendall (whose semantics you may have misunderstood).

Upvotes: 1

Related Questions