Home > Net >  python socket multiclients sending,
python socket multiclients sending,

Time:09-17

I got a problem python socket server send data only to one client which was added last. I tried use sendto(data, addr) but it doesn't work all the time. The server is supposed to work as a remote command line in windows. The server communicates with one client and it doesn't have any problem with it, but with more it just doesn't work. Python version: 3.9 Maybe someone will be able to help me? Here I put the code:

SERVER

import socket
import sys
import threading
HEADER = 64
PORT = 5050
SERVER = "192.168.0.117"
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "!DISCONNECT"

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
server.settimeout(2)
clients = []


def handle_client(conn, addr):
    print(f"[NEW CONNECTION] {addr} connected.")
    clients.append(addr)
    print(clients)
    connected = True
    while connected:
        command = input("[SERVER] => ")
        for client in clients:
            conn.sendto(command.encode(FORMAT), client)
            print(f"Sending data: {command} to {client}")
    conn.close()


def start():
    server.listen()
    print(f"[LISTENING] Server is listening on {SERVER}")
    while True:
        try:
            conn, addr = server.accept()
            thread = threading.Thread(target=handle_client, args=(conn, addr))
            thread.start()
        except socket.timeout:
            continue
        except socket.error as e:
            print(e)
            sys.exit(1)


if __name__ == '__main__':
    start()

And here is client:

import socket
import os
import sys
HEADER = 64
PORT = 5050
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "!DISCONNECT"
SERVER = "192.168.0.117"
ADDR = (SERVER, PORT)

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(ADDR)


# it doesn't work yet
def send(msg):
    message = msg.encode(FORMAT)
    msg_length = len(message)
    send_length = str(msg_length).encode(FORMAT)
    send_length  = b' ' * (HEADER - len(send_length))
    client.send(send_length)
    client.send(message)
    

def command_bot(command):
    if len(command) > 1:
        try:
            comm = ""
            for x in command:
                comm  = x   " "
            os.system(comm)
            print(comm)
        except os.error as e:
            print(e)
            sys.exit(1)

    
def start():
    while True:
        command = str(client.recv(2048).decode(FORMAT) " ")
        comm = []
        y = ""
        for x in command:
            if x != " ":
                y  = x
            else:
                comm.append(y)
                y = ""
        if comm[-1] == "":
            comm = comm[:-1]
        command_bot(comm)

if __name__ == '__main__':
    start()

CodePudding user response:

hi again if someone will be want send data to only one client here a put the code I think it looks amateurish but it works. Enter command: sendto -c <client's address ip> <command> example: sendto -c 192.168.0.117 start www.google.com

def handle_client():
    while True:
        command = input("[SERVER] => ")
        command = command.split()
        for client in list(clients):
            try:
                if len(command) > 1:
                    if len(command) > 3:
                        if client[1] == (command[2], client[1][1]) and command[0] == "sendto" and command[1] == "-c":
                            c = command[3:]
                            comm = ""
                            for x in c:
                                comm  = x   " "
                            client[0].sendall(comm.encode(FORMAT))
                            print(f"Sending data: '{comm}' to {client[1]}")
                            continue
                if len(command) > 0 and command[0] != "sendto":
                    comm = ""
                    for x in command:
                        comm  = x   " "
                    client[0].sendall(comm.encode(FORMAT))
                    print(f"Sending data: '{comm}' to {client[1]}")

            except Exception as ex:
                print("ERROR:", ex)
                print("remove client:", client[1])
                clients.remove(client)

CodePudding user response:

The server code is creating a thread for each client which is getting input from the user and iterating over all the client connections, not just the new client connection. You may want to consider having one thread iterate over the clients and add the client connection in the main loop.

Try this updated server code which works with multiple client connections:

def handle_client():
    while True:
        command = input("[SERVER] => ")
        for client in list(clients):
            conn = client[0]
            try:
                conn.sendall(command.encode(FORMAT))
                print(f"Sending data: {command} to {client[1]}")
            except Exception as ex:
                print ("ERROR:", ex)
                print("remove client:", client[1])
                clients.remove(client)
                try:
                    conn.close()
                except:
                    pass

def start():
    server.listen()
    print(f"[LISTENING] Server is listening on {SERVER}")
    threading.Thread(target=handle_client).start()
    while True:
        try:
            conn, addr = server.accept()
            print("client:", addr)
            clients.append((conn, addr))
        except socket.timeout:
            continue
        except socket.error as e:
            print(e)
            sys.exit(1)
  • Related