如何在 TCP 服务器中使用 Tornado.gen.coroutine?

How to use Tornado.gen.coroutine in TCP Server?

我用 Tornado 写了一个 Tcp 服务器。 这是代码:

#! /usr/bin/env python
#coding=utf-8

from tornado.tcpserver import TCPServer
from tornado.ioloop import IOLoop
from tornado.gen import *
class TcpConnection(object):
    def __init__(self,stream,address):
        self._stream=stream
        self._address=address
        self._stream.set_close_callback(self.on_close)
        self.send_messages()


    def send_messages(self):
        self.send_message(b'hello \n')
        print("next")
        self.read_message()

        self.send_message(b'world \n')

        self.read_message()


    def read_message(self):
        self._stream.read_until(b'\n',self.handle_message)

    def handle_message(self,data):
        print(data)

    def send_message(self,data):

        self._stream.write(data)

    def on_close(self):
        print("the monitored %d has left",self._address)

class MonitorServer(TCPServer):

    def handle_stream(self,stream,address):
        print("new connection",address,stream)
        conn = TcpConnection(stream,address)

if  __name__=='__main__':
    print('server start .....')
    server=MonitorServer()
    server.listen(20000)
    IOLoop.instance().start()

我遇到了一些错误 assert self._read_callback is None, "Already reading",我猜错误是因为多个命令同时从套接字读取 time.and 然后我将函数 send_messages 更改为 tornado.gen.coroutine.here 是代码:

@gen.coroutine
    def send_messages(self):
        yield self.send_message(b'hello \n')
        response1 = yield self.read_message()
        print(response1)
        yield self.send_message(b'world \n')
        print((yield self.read_message()))

但还有其他一些错误。代码似乎在 yield self.send_message(b'hello \n') 之后停止,下面的代码似乎没有执行。 我该怎么办?如果您知道任何带有 tornado.gen.coroutine 的 Tornado tcpserver(不是 HTTP!)代码,请告诉 me.I 将不胜感激任何链接!

send_messages() 使用 yield 调用 send_message()read_message(),但这些方法不是协程,因此会引发异常。

你没有看到异常的原因是你调用了 send_messages() 而没有产生它,所以异常无处可去(垃圾收集器最终应该注意到并打印异常,但这可能需要很长时间)。每当你调用协程时,你应该使用 yield 等待它完成,或者 IOLoop.current().spawn_callback() 到 运行 "background" 中的协程(这告诉 Tornado 你做不打算 yield 协程,所以它会在异常发生时立即打印)。另外,无论何时你覆盖一个方法,你都应该阅读文档以查看是否允许协程(当你覆盖 TCPServer.handle_stream() 时你可以使它成为协程,但 __init__() 可能不是协程)。

记录异常后,下一步就是修复它。您可以制作 send_message()read_message() 协程(摆脱过程中的 handle_message() 回调),或者您可以使用 tornado.gen.Task() 从协程中调用协程式代码.我通常建议在任何地方都使用协程。