You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

65 lines
2.1 KiB

  1. #!/usr/bin/env python3.7
  2. import socket # socket, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR
  3. import logging
  4. import threading
  5. from ClientConnection import ClientConnection
  6. class Server(object):
  7. """
  8. A simple chat application server
  9. """
  10. clients = []
  11. soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  12. soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  13. def __init__(self, host: str, port: int, maxClients=64):
  14. self.host = host
  15. self.port = port
  16. self.soc.bind((host, port))
  17. self.maxClients = maxClients
  18. def run(self) -> None:
  19. """
  20. Start the server and start to listen for incoming connection
  21. """
  22. self.soc.listen(self.maxClients)
  23. logging.info('Start listening on {}:{} maximum {} clients'.format(
  24. self.host, self.port, self.maxClients))
  25. while True:
  26. conn, addr = self.soc.accept()
  27. client = ClientConnection(self, conn, addr)
  28. msg = '{}:{} has joined the chat.'.format(
  29. client.addr[0], client.addr[1])
  30. self._announce(msg)
  31. self.clients.append(client)
  32. threading.Thread(target=client.serve).start()
  33. def removeClient(self, client: ClientConnection) -> None:
  34. """
  35. Remove client from this server list of connected clients
  36. """
  37. msg = '{}:{} has left the chat.'.format(client.addr[0], client.addr[1])
  38. self.clients.remove(client)
  39. self._announce(msg)
  40. def _announce(self, announcement: str) -> None:
  41. """
  42. Send announcement from system to all connected clients
  43. """
  44. msg = '[system] {}'.format(announcement)
  45. logging.info(msg)
  46. for client in self.clients:
  47. client.send(msg)
  48. def sendToAll(self, sender: ClientConnection, msg: str) -> None:
  49. """
  50. Broadcast message from one client to other clients
  51. """
  52. msg = '[{}:{}] {}'.format(sender.addr[0], sender.addr[1], msg)
  53. logging.info(msg)
  54. for client in self.clients:
  55. if client != sender:
  56. client.send(msg)