This post presents a TCP/IP host which allows multiple client connection.
Run the script to start the host, it will wait for client connections through port 5000. Then, on the same machine, use a chatting tool such as telnet
to connect to the host. You may open two separate terminal consoles and run telnet on each of them. For each copy, issue the following command to the server:
- q - close a client connection without closing the server.
- x - close all client connections and the server.
- other - send text message to the server.
Source Code
#!/usr/bin/env python3 # Title : TCP Server (multiple clients) # Author : Michael Mui # Date : 29/01/2024 # Remark : You may use telnet to talk to this server # # telnet -r 127.0.0.1 5000 # # The server accepts connection from multiple clients. # It can broadcast data sent by a client to all other clients import socket, select class MultiClientHost(object): def __init__(self, ip, port, maxClient): self.ip = ip self.port = port self.maxClient = maxClient self.connSockets = [] # all open sockets self.socket = None self.endServer = True self.noteStartUp = "TCP/IP Host is running..." # send message to all sockets except # server socket and source socket def broadcast(self, srcSock, message): for s in self.connSockets: if s != self.socket and s != srcSock: bMsg = message.encode('utf-8') s.send(bMsg) # handle data sent by a client socket # bdata - binary data for the info sent # srcsock - the client socket sending the info def handler(self, srcSock, bdata): sdata = bdata.decode('utf-8').strip() # abstract method to be overriden by # child class addr = srcSock.getpeername() # addr = (client_ip, client_port) if sdata == "a": # action 1 pass def startUp(self): self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.bind((self.ip, self.port)) self.socket.listen(self.maxClient) self.connSockets.append(self.socket) self.endServer = False print(self.noteStartUp) while not self.endServer: # get the sockets which are ready # to be read through select rsocks, wsocks, esocks = \ select.select(self.connSockets,[],[]) for s in rsocks: if s == self.socket: # handle new client connection newCSock, addr = self.socket.accept() self.connSockets.append(newCSock) print("Client (%s, %s): Connected" % addr) else: # data received from client try: data = s.recv(1024) except: addr = s.getpeername() print("Client (%s, %s): Offline" % addr) s.close() self.connSockets.remove(s) continue if data: # valid data received from client self.handler(s, data) self.socket.close() # Define the handler in the host for client message # # Message Action taken by the server # ------- -------------------------------------- # q Close the client # x Close the client and close the server # other Print the message in the server # class MCH(MultiClientHost): # handling data sent by a client socket # sdata - string for the info sent # srcsock - the client socket sending the info def handler(self, srcSock, bdata): print(bdata) sdata = bdata.decode('utf-8').strip() addr = srcSock.getpeername() if sdata == "q" or sdata == "Q": # action print("Client (%s, %s): Quit" % addr) srcSock.close() self.connSockets.remove(srcSock) elif sdata=="x" or sdata=="X": # action mstr = "Sever: Closed by (%s, %s).\n" % addr print(mstr) self.broadcast(self.socket, mstr) self.endServer = True else: #print("Client (%s, %s): Message"% addr) print(sdata) IP = "127.0.0.1" PORT = 5000 MAXCLIENT = 5 hst = MCH(IP, PORT, MAXCLIENT) hst.startUp()
If you want to connect to the host with another machine on the network, you should change the line:
IP = "127.0.0.1"
in the script to IP = ""
.Output
- Start the host on a terminal console.
Host
# python3 tcpser.py TCP/IP Host is running...
- Start Client A using
telnet
on another terminal console. Send a message to the host after connecting to it.Client A
# telnet -r 127.0.0.1 5000 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. Hello host, I am Client A.
Host
# python3 tcpser.py TCP/IP Host is running... Client (127.0.0.1, 49012): Connected b'Hello host, I am Client A.\r\n' Hello host, I am Client A.
- Start Client B using
telnet
on the third terminal console. Send a message to the host after connecting to it.Client B
# telnet -r 127.0.0.1 5000 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. Hi host, here is Client B. Can you see me?
Host
# python3 tcpser.py TCP/IP Host is running... Client (127.0.0.1, 49012): Connected b'Hello host, I am Client A.\r\n' Hello host, I am Client A. Client (127.0.0.1, 51878): Connected b'Hi host, here is Client B. Can you see me?\r\n' Hi host, here is Client B. Can you see me?
- Quit Client A by sending a q to the host.
Client A
# telnet -r 127.0.0.1 5000 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. Hello host, I am Client A. q Connection closed by foreign host. # _
Host
# python3 tcpser.py TCP/IP Host is running... Client (127.0.0.1, 49012): Connected b'Hello host, I am Client A.\r\n' Hello host, I am Client A. Client (127.0.0.1, 51878): Connected b'Hi host, here is Client B. Can you see me?\r\n' Hi host, here is Client B. Can you see me? b'q\r\n' Client (127.0.0.1, 49012): Quit
- Use the previous Client A console to join the host again. This time, name itself as Client A1. Notice that the socket number 41286 for Client A1 is different from the previous one 49012, as it is assigned by the OS randomly.
Client A1
# telnet -r 127.0.0.1 5000 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. Hi this is Client A1, the reborn of Client A
Host
# python3 tcpser.py TCP/IP Host is running... Client (127.0.0.1, 49012): Connected b'Hello host, I am Client A.\r\n' Hello host, I am Client A. Client (127.0.0.1, 51878): Connected b'Hi host, here is Client B. Can you see me?\r\n' Hi host, here is Client B. Can you see me? b'q\r\n' Client (127.0.0.1, 49012): Quit Client (127.0.0.1, 41286): Connected b'Hi this is Client A1, the reborn of Client A\r\n' Hi this is Client A1, the reborn of Client A
- Use Client B console to send a x to the host. This will terminate the host, and will disconnect Client A1 and Client B from it.
Client B
# telnet -r 127.0.0.1 5000 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. Hi host, here is Client B. Can you see me? x Sever: Closed by (127.0.0.1, 51878). Connection closed by foreign host. # _
Host
# python3 tcpser.py TCP/IP Host is running... Client (127.0.0.1, 49012): Connected b'Hello host, I am Client A.\r\n' Hello host, I am Client A. Client (127.0.0.1, 51878): Connected b'Hi host, here is Client B. Can you see me?\r\n' Hi host, here is Client B. Can you see me? b'q\r\n' Client (127.0.0.1, 49012): Quit Client (127.0.0.1, 41286): Connected b'Hi this is Client A1, the reborn of Client A\r\n' Hi this is Client A1, the reborn of Client A b'x\r\n' Sever: Closed by (127.0.0.1, 51878). # _
Notice that Client A1 also receives a messageSever: Closed by (127.0.0.1, 51878)
from the host as the message is issued by the broadcast function of the host.Client A1
# telnet -r 127.0.0.1 5000 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. Hi this is Client A1, the reborn of Client A Sever: Closed by (127.0.0.1, 51878). Connection closed by foreign host. # _
No comments:
Post a Comment