简体   繁体   中英

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

i write a Tcp Server with Tornado. here is the code:

#! /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()

And i face some eorror assert self._read_callback is None, "Already reading" ,i guess the eorror is because multiple commands to read from socket at the same time.and then i change the function send_messages with tornado.gen.coroutine.here is code:

@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()))

but there are some other errors. the code seem to stop after yield self.send_message(b'hello \\n') ,and the following code seem not to execute. how should i do about it ? If you're aware of any Tornado tcpserver (not HTTP!) code with tornado.gen.coroutine,please tell me.I would appreciate any links!

send_messages() calls send_message() and read_message() with yield , but these methods are not coroutines, so this will raise an exception.

The reason you're not seeing the exception is that you called send_messages() without yielding it, so the exception has nowhere to go (the garbage collector should eventually notice and print the exception, but that can take a long time). Whenever you call a coroutine, you should either use yield to wait for it to finish, or IOLoop.current().spawn_callback() to run the coroutine in the "background" (this tells Tornado that you do not intend to yield the coroutine, so it will print the exception as soon as it occurs). Also, whenever you override a method you should read the documentation to see whether coroutines are allowed (when you override TCPServer.handle_stream() you can make it a coroutine, but __init__() may not be a coroutine).

Once the exception is getting logged, the next step is to fix it. You can either make send_message() and read_message() coroutines (getting rid of the handle_message() callback in the process), or you can use tornado.gen.Task() to call coroutine-style code from a coroutine. I generally recommend using coroutines everywhere.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM