server.py 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import socket
  2. import logging
  3. from traceback import format_exc
  4. from websocket import WebSocket
  5. from exceptions import InvalidRequest
  6. class Server(object):
  7. def __init__(self, port, address='', log_level=logging.INFO, protocols=[]):
  8. logging.basicConfig(level=log_level,
  9. format='%(asctime)s: %(levelname)s: %(message)s',
  10. datefmt='%H:%M:%S')
  11. self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  12. self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  13. logging.info('Starting server at %s:%d', address, port)
  14. self.sock.bind((address, port))
  15. self.sock.listen(5)
  16. self.clients = []
  17. self.protocols = protocols
  18. def run(self):
  19. while True:
  20. try:
  21. sock, address = self.sock.accept()
  22. client = Client(self, sock, address)
  23. client.handshake()
  24. self.clients.append(client)
  25. logging.info('Registered client %s', client)
  26. client.run_threaded()
  27. except InvalidRequest as e:
  28. logging.error('Invalid request: %s', e.message)
  29. except KeyboardInterrupt:
  30. logging.info('Received interrupt, stopping server...')
  31. break
  32. except Exception as e:
  33. logging.error(format_exc(e))
  34. def remove_client(self, client, code, reason):
  35. self.clients.remove(client)
  36. self.onclose(client, code, reason)
  37. def onopen(self, client):
  38. logging.debug('Opened socket to %s' % client)
  39. def onmessage(self, client, message):
  40. logging.debug('Received %s from %s' % (message, client))
  41. def onping(self, client, payload):
  42. logging.debug('Sent ping "%s" to %s' % (payload, client))
  43. def onpong(self, client, payload):
  44. logging.debug('Received pong "%s" from %s' % (payload, client))
  45. def onclose(self, client, code, reason):
  46. msg = 'Closed socket to %s' % client
  47. if code is not None:
  48. msg += ' [%d]' % code
  49. if len(reason):
  50. msg += ' "%s"' % reason
  51. logging.debug(msg)
  52. class Client(WebSocket):
  53. def __init__(self, server, sock, address):
  54. super(Client, self).__init__(sock)
  55. self.server = server
  56. self.address = address
  57. def onopen(self):
  58. self.server.onopen(self)
  59. def onmessage(self, message):
  60. self.server.onmessage(self, message)
  61. def onping(self, payload):
  62. self.server.onping(self, payload)
  63. def onpong(self, payload):
  64. self.server.onpong(self, payload)
  65. def onclose(self, code, reason):
  66. self.server.remove_client(self, code, reason)
  67. def __str__(self):
  68. return '<Client at %s:%d>' % self.address
  69. if __name__ == '__main__':
  70. import sys
  71. port = int(sys.argv[1]) if len(sys.argv) > 1 else 80
  72. Server(port, log_level=logging.DEBUG).run()