Nie można użyć socket.settimeout()
, ponieważ jest przeznaczony do blokowania IO, a Tornado zapewnia niezablokowanie IO.
Tornado jest wysoce zorientowane na Web i HTTP IO i nie pozwala na programowanie sieci niskiego poziomu bez ekstremalnego bólu (źródła o IOStream
są przerażające).
Najlepszym sposobem ustawienia limitu czasu na gnieździe jest użycie select.select()
, select.poll()
itd., Ale trudno jest zintegrować takie podejście z Tornadem.
Udało mi się wykonać odczyty z limitami czasu, używając kombinacji gen.with_timeout
i brudnego hacka do czyszczenia stanu strumienia.
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)
Powodzenia!