#!/usr/bin/env python3.7 import socket # socket, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR import logging import threading from ClientConnection import ClientConnection class Server(object): """ A simple chat application server """ clients = [] soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) def __init__(self, host: str, port: int, maxClients=64): self.host = host self.port = port self.soc.bind((host, port)) self.maxClients = maxClients def run(self) -> None: """ Start the server and start to listen for incoming connection """ self.soc.listen(self.maxClients) logging.info('Start listening on {}:{} maximum {} clients'.format( self.host, self.port, self.maxClients)) while True: conn, addr = self.soc.accept() client = ClientConnection(self, conn, addr) msg = '{}:{} has joined the chat.'.format( client.addr[0], client.addr[1]) self._announce(msg) self.clients.append(client) threading.Thread(target=client.serve).start() def removeClient(self, client: ClientConnection) -> None: """ Remove client from this server list of connected clients """ msg = '{}:{} has left the chat.'.format(client.addr[0], client.addr[1]) self.clients.remove(client) self._announce(msg) def _announce(self, announcement: str) -> None: """ Send announcement from system to all connected clients """ msg = '[system] {}'.format(announcement) logging.info(msg) for client in self.clients: client.send(msg) def sendToAll(self, sender: ClientConnection, msg: str) -> None: """ Broadcast message from one client to other clients """ msg = '[{}:{}] {}'.format(sender.addr[0], sender.addr[1], msg) logging.info(msg) for client in self.clients: if client != sender: client.send(msg)