'Is there a way to send message to a specific client in a multithreaded TCP server?
I have made a tcp multithread server which is always listening to new connections and at the same time handling existing clients. If i have 2 clients, lets say A and B. Is there a way to send a message from the server to a specific client either A or B only? Here is my code
import socket
import threading
HEADER = 80
PORT = 9000
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "!DISCONNECT"
VITA_POSITIVE = "0000"
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
def handle_client(conn, addr):
print(f"[NEW CONNECTION] {addr} connected.")
connected = True
while connected:
conn.send("VITA".encode(FORMAT))
vita_response_iconet = conn.recv(HEADER).decode(FORMAT)
print(vita_response_iconet)
if vita_response_iconet == VITA_POSITIVE:
print("VITA received from Iconet")
else:
print("VITA not received from Iconet")
conn.close()
def start():
server.listen()
print(f"[LISTENING] Server is listening on {SERVER}")
while True:
conn, addr = server.accept()
print(conn)
print(addr)
thread = threading.Thread(target=handle_client, args=(conn, addr))
thread.start()
print(f"[ACTIVE CONNECTIONS] {threading.active_count() - 1}")
print("[STARTING] server is starting...")
start()
here is the modified code where i have put in the ip address of the clients and trying to run but i am encountering key error issues
import socket, threading
import time
HEADER = 80
PORT = 9000
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "!DISCONNECT"
VITA_POSITIVE = "0000"
my_timer = 0
class ClientThread(threading.Thread):
def __init__(self, conn: socket.socket, addr: str):
threading.Thread.__init__(self)
self.conn = conn
self.addr = addr
def send(self, msg: str):
self.conn.sendall(msg.encode())
def run(self):
print(f"[NEW CONNECTION] {self.addr} connected.")
connected = True
while connected:
clients["10.14.0.1"].send("VITA".encode(FORMAT))
vita_response_iconet = clients["10.14.0.1"].recv(HEADER).decode(FORMAT)
print(vita_response_iconet)
if vita_response_iconet == VITA_POSITIVE:
print("VITA received from Iconet")
vita_iconet = 1
else:
print("VITA not received from Iconet")
vita_iconet = 0
clients["10.14.0.1"].send("VITA".encode(FORMAT))
vita_response_robot = clients["10.14.0.1"].recv(HEADER).decode(FORMAT)
print(vita_response_robot)
if vita_response_iconet == VITA_POSITIVE:
print("VITA received from Robot")
vita_robot = 1
else:
print("VITA not received from Robot")
vita_robot = 0
if vita_iconet and vita_robot == 1:
my_timer = 0
else:
my_timer = my_timer
self.conn.close()
def countup():
global my_timer
for x in range(1, my_timer+1):
time.sleep(1)
countup_thread = threading.Thread(target=countup)
countup_thread.start()
def start():
server.listen()
print(f"[LISTENING] Server is listening on {SERVER}")
while True:
conn, addr = server.accept()
print('interesting')
print(conn)
print(addr)
thread = ClientThread(conn, addr)
print ('be ready')
thread.start()
clients[addr] = thread
print(f"[ACTIVE CONNECTIONS] {threading.active_count() - 2}")
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
clients = {}
connections = threading.Thread(target=start)
connections.start()
print("[STARTING] server is starting...")
start()
Solution 1:[1]
You can do this by creating a class for clients, like this
import socket, threading
HEADER = 80
PORT = 9000
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "!DISCONNECT"
VITA_POSITIVE = "0000"
class ClientThread(threading.Thread):
def __init__(self, conn: socket.socket, addr: str):
threading.Thread.__init__(self)
self.conn = conn
self.addr = addr
def send(self, msg: str):
self.conn.sendall(msg.encode())
def run(self):
print(f"[NEW CONNECTION] {self.addr} connected.")
connected = True
while connected:
self.conn.send("VITA".encode(FORMAT))
vita_response_iconet = self.conn.recv(HEADER).decode(FORMAT)
print(vita_response_iconet)
if vita_response_iconet == VITA_POSITIVE:
print("VITA received from Iconet")
else:
print("VITA not received from Iconet")
self.conn.close()
def start():
server.listen()
print(f"[LISTENING] Server is listening on {SERVER}")
while True:
conn, addr = server.accept()
print(conn)
print(addr)
thread = ClientThread(conn, addr)
thread.start()
clients[addr] = thread
print(f"[ACTIVE CONNECTIONS] {threading.active_count() - 1}")
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
clients = {}
print("[STARTING] server is starting...")
start()
Now, you can use clients[client_address].send(data_you_want_to_send)
to send a message to only this client
EDIT
This code technically allows you to send a message to a specific client but does not leave too many places to do so.
To solve this problem, you can put the task of accepting connections in a threading.Thread
like this
import socket, threading, time
HEADER = 80
PORT = 9000
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "!DISCONNECT"
VITA_POSITIVE = "0000"
class ClientThread(threading.Thread):
def __init__(self, conn: socket.socket, addr: str):
threading.Thread.__init__(self)
self.conn = conn
self.addr = addr
def send(self, msg: str):
self.conn.sendall(msg.encode())
def run(self):
print(f"[NEW CONNECTION] {self.addr} connected.")
connected = True
while connected:
self.conn.send("VITA".encode(FORMAT))
vita_response_iconet = self.conn.recv(HEADER).decode(FORMAT)
print(vita_response_iconet)
if vita_response_iconet == VITA_POSITIVE:
print("VITA received from Iconet")
else:
print("VITA not received from Iconet")
self.conn.close()
def start():
server.listen()
print(f"[LISTENING] Server is listening on {SERVER}")
while True:
conn, addr = server.accept()
print(conn)
print(addr)
thread = ClientThread(conn, addr)
thread.start()
clients[addr] = thread
print(f"[ACTIVE CONNECTIONS] {threading.active_count() - 1}")
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
clients = {}
connections = threading.Thread(target=start)
connections.start()
print("[STARTING] server is starting...")
time.sleep(0.5)
while True:
client = input("Client you want to send a message : ") # Enter the address of the client you want to send a message
if client not in clients.keys():
print("This client is not connected")
continue
message = input("Message you want to send : ")
clients[client].send(message)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |