r"""A non-blocking, single-threaded TCP server. To use `TCPServer`, define a subclass which overrides the `handle_stream` method. For example, a simple echo server could be defined like this:: from tornado.tcpserver import TCPServer from tornado.iostream import StreamClosedErro
| 41 | |
| 42 | |
| 43 | class TCPServer: |
| 44 | r"""A non-blocking, single-threaded TCP server. |
| 45 | |
| 46 | To use `TCPServer`, define a subclass which overrides the `handle_stream` |
| 47 | method. For example, a simple echo server could be defined like this:: |
| 48 | |
| 49 | from tornado.tcpserver import TCPServer |
| 50 | from tornado.iostream import StreamClosedError |
| 51 | |
| 52 | class EchoServer(TCPServer): |
| 53 | async def handle_stream(self, stream, address): |
| 54 | while True: |
| 55 | try: |
| 56 | data = await stream.read_until(b"\n") await |
| 57 | stream.write(data) |
| 58 | except StreamClosedError: |
| 59 | break |
| 60 | |
| 61 | To make this server serve SSL traffic, send the ``ssl_options`` keyword |
| 62 | argument with an `ssl.SSLContext` object. For compatibility with older |
| 63 | versions of Python ``ssl_options`` may also be a dictionary of keyword |
| 64 | arguments for the `ssl.SSLContext.wrap_socket` method.:: |
| 65 | |
| 66 | ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) |
| 67 | ssl_ctx.load_cert_chain(os.path.join(data_dir, "mydomain.crt"), |
| 68 | os.path.join(data_dir, "mydomain.key")) |
| 69 | TCPServer(ssl_options=ssl_ctx) |
| 70 | |
| 71 | `TCPServer` initialization follows one of three patterns: |
| 72 | |
| 73 | 1. `listen`: single-process:: |
| 74 | |
| 75 | async def main(): |
| 76 | server = TCPServer() |
| 77 | server.listen(8888) |
| 78 | await asyncio.Event().wait() |
| 79 | |
| 80 | asyncio.run(main()) |
| 81 | |
| 82 | While this example does not create multiple processes on its own, when |
| 83 | the ``reuse_port=True`` argument is passed to ``listen()`` you can run |
| 84 | the program multiple times to create a multi-process service. |
| 85 | |
| 86 | 2. `add_sockets`: multi-process:: |
| 87 | |
| 88 | sockets = bind_sockets(8888) |
| 89 | tornado.process.fork_processes(0) |
| 90 | async def post_fork_main(): |
| 91 | server = TCPServer() |
| 92 | server.add_sockets(sockets) |
| 93 | await asyncio.Event().wait() |
| 94 | asyncio.run(post_fork_main()) |
| 95 | |
| 96 | The `add_sockets` interface is more complicated, but it can be used with |
| 97 | `tornado.process.fork_processes` to run a multi-process service with all |
| 98 | worker processes forked from a single parent. `add_sockets` can also be |
| 99 | used in single-process servers if you want to create your listening |
| 100 | sockets in some way other than `~tornado.netutil.bind_sockets`. |
no outgoing calls