run_tcp_server.py 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. # SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
  2. # SPDX-License-Identifier: Unlicense OR CC0-1.0
  3. import argparse
  4. import socket
  5. from threading import Event, Thread
  6. DEF_PORT = 3333
  7. class TcpServer(object):
  8. def __init__(self, port, family_addr, persist=False, timeout=60): # type: ignore
  9. self.port = port
  10. self.socket = socket.socket(family_addr, socket.SOCK_STREAM)
  11. self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  12. self.socket.settimeout(timeout)
  13. self.shutdown = Event()
  14. self.persist = persist
  15. self.family_addr = family_addr
  16. self.server_thread = None
  17. def __enter__(self): # type: ignore
  18. try:
  19. self.socket.bind(('', self.port))
  20. except socket.error as e:
  21. print('Bind failed:{}'.format(e))
  22. raise
  23. self.socket.listen(1)
  24. print('Starting server on port={} family_addr={}'.format(self.port, self.family_addr))
  25. self.server_thread = Thread(target=self.run_server)
  26. self.server_thread.start()
  27. return self
  28. def __exit__(self, exc_type, exc_value, traceback) -> None: # type: ignore
  29. if self.persist:
  30. sock = socket.socket(self.family_addr, socket.SOCK_STREAM)
  31. sock.connect(('localhost', self.port))
  32. sock.sendall(b'Stop', )
  33. sock.close()
  34. self.shutdown.set()
  35. self.shutdown.set()
  36. self.server_thread.join()
  37. self.socket.close()
  38. def run_server(self) -> None:
  39. while not self.shutdown.is_set():
  40. try:
  41. conn, address = self.socket.accept() # accept new connection
  42. print('Connection from: {}'.format(address))
  43. conn.setblocking(1)
  44. data = conn.recv(1024)
  45. if not data:
  46. return
  47. data = data.decode()
  48. print('Received data: ' + data)
  49. reply = 'OK: ' + data
  50. conn.send(reply.encode())
  51. conn.close()
  52. except socket.timeout:
  53. print(f'socket accept timeout ({self.socket.timeout}s)')
  54. except socket.error as e:
  55. print('Running server failed:{}'.format(e))
  56. raise
  57. if not self.persist:
  58. break
  59. def main() -> None:
  60. parser = argparse.ArgumentParser()
  61. parser.add_argument('--port', default=DEF_PORT, type=int, help='TCP server port')
  62. parser.add_argument('--ipv6', action='store_true', help='Create IPv6 server.')
  63. parser.add_argument('--timeout', default=10, type=int, help='socket accept/recv timeout.')
  64. args = parser.parse_args()
  65. if args.ipv6:
  66. family = socket.AF_INET6
  67. else:
  68. family = socket.AF_INET
  69. with TcpServer(args.port, family, persist=True, timeout=args.timeout):
  70. input('Server Running. Press Enter or CTRL-C to exit...\n')
  71. if __name__ == '__main__':
  72. main()