Tornado 基于基本IOStream的 TCP 服务器
class tornado.tcpserver.TCPServer(ssl_options: Union[Dict[str, Any], ssl.SSLContext, None] = None, max_buffer_size: Optional[int] = None, read_chunk_size: Optional[int] = None)
一个非阻塞的单线程 TCP 服务器。
要使用 TCPServer
,请定义一个覆盖 handle_stream
方法的子类。 例如,一个简单的echo服务器可以这样定义:
from tornado.tcpserver import TCPServer
from tornado.iostream import StreamClosedError
from tornado import gen
class EchoServer(TCPServer):
async def handle_stream(self, stream, address):
while True:
try:
data = await stream.read_until(b"\n")
await stream.write(data)
except StreamClosedError:
break
要使此服务器为 SSL 流量提供服务,请发送带有 ssl.SSLContext
对象的 ssl_options
关键字参数。 为了与旧版本的 Python 兼容,ssl_options
也可能是 ssl.wrap_socket
方法的关键字参数字典。:
ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
ssl_ctx.load_cert_chain(os.path.join(data_dir, "mydomain.crt"),
os.path.join(data_dir, "mydomain.key"))
TCPServer(ssl_options=ssl_ctx)
TCPServer
初始化遵循以下三种模式之一:
1、listen
:简单的单进程:
server = TCPServer()
server.listen(8888)
IOLoop.current().start()
2、bind
/start
:简单的多进程:
server = TCPServer()
server.bind(8888)
server.start(0) # Forks multiple sub-processes
IOLoop.current().start()
使用此接口时,不得将 IOLoop
传递给 TCPServer
构造函数。 start
将始终在默认单例 IOLoop
上启动服务器。
3、add_sockets
:先进的多进程:
sockets = bind_sockets(8888)
tornado.process.fork_processes(0)
server = TCPServer()
server.add_sockets(sockets)
IOLoop.current().start()
add_sockets
接口更复杂,但它可以与 tornado.process.fork_processes
一起使用,以便在分叉发生时为您提供更大的灵活性。 如果您想以非 bind_sockets
的方式创建侦听套接字,add_sockets
也可用于单进程服务器。
3.1 版中的新功能:max_buffer_size
参数。
在 5.0 版更改: io_loop
参数已被删除。
listen(port: int, address: str = '') → None
开始接受给定端口上的连接。
可以多次调用此方法来侦听多个端口。 监听立即生效; 之后无需调用 TCPServer.start
。 但是,必须启动 IOLoop
add_sockets(sockets: Iterable[socket.socket]) → None。
使此服务器开始接受给定套接字上的连接。
sockets
参数是一个套接字对象列表,例如由 bind_sockets
返回的那些。 add_sockets
通常与该方法和 tornado.process.fork_processes
结合使用,以更好地控制多进程服务器的初始化。
add_socket(socket: socket.socket) → None
add_sockets
的单一版本。 采用单个套接字对象。
bind(port: int, address: Optional[str] = None, family: socket.AddressFamily = <AddressFamily.AF_UNSPEC: 0>, backlog: int = 128, reuse_port: bool = False) → None
将此服务器绑定到给定地址上的给定端口。
要启动服务器,请调用 start
。 如果您想在单个进程中运行此服务器,您可以调用 listen
作为绑定和启动调用序列的快捷方式。
地址可以是 IP 地址或主机名。 如果是主机名,服务器将侦听与该名称关联的所有 IP 地址。 Address 可以是空字符串或 None 以侦听所有可用接口。 Family 可以设置为 socket.AF_INET
或 socket.AF_INET6
以限制 IPv4 或 IPv6 地址,否则将使用两者(如果可用)。
backlog
参数与 socket.listen
的含义相同。 重用端口参数与 bind_sockets
具有相同的含义。
在开始侦听多个端口或接口之前,可能会多次调用此方法。
在 4.4 版更改: 添加了 reuse_port
参数。
start(num_processes: Optional[int] = 1, max_restarts: Optional[int] = None) → None
在 IOLoop
中启动此服务器。
默认情况下,我们在这个进程中运行服务器,并且不会派生任何额外的子进程。
如果 num_processes
为 None
或 <= 0,我们会检测这台机器上可用的内核数量并派生该数量的子进程。 如果给定 num_processes
并且 > 1,我们将分叉特定数量的子进程。
由于我们使用进程而不是线程,因此任何服务器代码之间都没有共享内存。
请注意,多个进程与 autoreload
模块(或 tornado.web.Application
的 autoreload=True
选项,当 debug=True
时默认为 True
)不兼容。 当使用多个进程时,在调用 TCPServer.start(n)
之前不能创建或引用任何 IOLoop
。
Windows 不支持除 1 以外的 num_processes
值。
max_restarts
参数被传递给 fork_processes
。
在 6.0 版更改: 添加了 max_restarts
参数。
stop() → None
停止侦听新连接。
在服务器停止后,当前正在进行的请求可能仍会继续。
handle_stream(stream: tornado.iostream.IOStream, address: tuple) → Optional[Awaitable[None]]
重写以处理来自传入连接的新 IOStream
。
这个方法可能是协程; 如果是这样,它将记录异步引发的任何异常。 此协程不会阻止接受传入连接。
如果此 TCPServer
配置为 SSL
,则可能会在 SSL
握手完成之前调用 handle_stream
。 如果您需要验证客户端的证书或使用 NPN
/ALPN
,请使用 SSLIOStream.wait_for_handshake
。
在 4.2 版更改: 添加了将此方法作为协程的选项。