如何在 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()
从协程中调用协程式代码.我通常建议在任何地方都使用协程。
我用 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()
从协程中调用协程式代码.我通常建议在任何地方都使用协程。