6

如何为龙卷风 IOStream 设置超时?

我尝试通过以下方式构建 IOStream:

sock = socket.socket()
sock.settimeout(5)
self.stream = tornado.iostream.IOStream(sock)

但是当我打电话时stream.read_bytes(),它仍然会永远等待。

4

1 回答 1

2

您不能使用socket.settimeout(),因为它是为阻塞 IO 而设计的,而 Tornado 提供了非阻塞 IO。

Tornado 高度面向 Web 和 HTTP IO,它不允许在没有极度痛苦的情况下进行低级网络编程(来源IOStream令人恐惧)。

在套接字上设置超时的最佳方法是使用select.select(),select.poll()等,但是将这种方法与 Tornado 集成起来很痛苦。

gen.with_timeout我已经设法使用组合和脏黑客来清除流的状态来执行超时读取。

from tornado import gen
from tornado.ioloop import IOLoop
from tornado.tcpclient import TCPClient

timeout = 5
io_loop = IOLoop.current()
factory = TCPClient(io_loop=io_loop)

@gen.coroutine
def run():
    stream = yield factory.connect('127.0.0.1', 1234)
    try:
        future = stream.read_bytes(128)
        data = yield gen.with_timeout(
            timeout=io_loop.time() + timeout,
            future=future,
            io_loop=io_loop,
        )
    except gen.TimeoutError:
        # A dirty hack to cancel reading and to clear state of the stream, so
        # stream will be available for reading in future
        io_loop.remove_handler(stream.socket)
        state = (stream._state & ~io_loop.READ)
        stream._state = None
        stream._read_callback = None
        stream._read_future = None
        stream._add_io_state(state)

祝你好运!

于 2017-01-29T21:29:50.247 回答