Tornado 基于基本IOStream的 TCP 服務器

2022-03-10 11:53 更新

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 流量提供服務,請發(fā)送帶有 ?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? 一起使用,以便在分叉發(fā)生時為您提供更大的靈活性。 如果您想以非 ?bind_sockets的方式創(chuàng)建偵聽套接字,?add_sockets也可用于單進程服務器。

3.1 版中的新功能:?max_buffer_size ?參數。

在 5.0 版更改: ?io_loop? 參數已被刪除。

listen(port: int, address: str = '') → None

開始接受給定端口上的連接。

可以多次調用此方法來偵聽多個端口。 監(jiān)聽立即生效; 之后無需調用 ?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)之前不能創(chuàng)建或引用任何 ?IOLoop?。

Windows 不支持除 1 以外的 ?num_processes值。

?max_restarts參數被傳遞給 ?fork_processes?。

在 6.0 版更改: 添加了 ?max_restarts參數。

stop() → None

停止偵聽新連接。

在服務器停止后,當前正在進行的請求可能仍會繼續(xù)。

handle_stream(stream: tornado.iostream.IOStream, address: tuple) → Optional[Awaitable[None]]

重寫以處理來自傳入連接的新 ?IOStream?。

這個方法可能是協程; 如果是這樣,它將記錄異步引發(fā)的任何異常。 此協程不會阻止接受傳入連接。

如果此 ?TCPServer配置為 ?SSL?,則可能會在 ?SSL握手完成之前調用 ?handle_stream?。 如果您需要驗證客戶端的證書或使用 ?NPN?/?ALPN?,請使用 ?SSLIOStream.wait_for_handshake?。

在 4.2 版更改: 添加了將此方法作為協程的選項。


以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號