2015-07-11 47 views
0

我用Tornado編寫了一個Tcp服務器。 這裏是代碼:如何在TCP Server中使用Tornado.gen.coroutine?

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

而且我面對一些eorror assert self._read_callback is None, "Already reading",我猜eorror是因爲多個命令從插座在同一time.and讀的話,我改變功能send_messages與tornado.gen.coroutine其中有代碼:

@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 tcpserver(不是HTTP!)代碼與tornado.gen.coroutine,請告訴我。我將不勝感激任何鏈接!

回答

3

send_messages()調用send_message()read_message()yield,但這些方法不是協程,所以這會引發異常。

你沒有看到異常的原因是因爲你調用了send_messages()而沒有產生異常,所以異常無處可去(垃圾回收器最終應該注意並打印異常,但這可能需要很長時間)。每當你調用一個協程時,你應該使用yield等待它完成,或者IOLoop.current().spawn_callback()在「背景」中運行協程(這告訴Tornado你​​不打算產生協程,所以它會打印異常一旦它發生)。另外,每當你重寫一個方法時,你應該閱讀文檔以查看協程是否被允許(當你重寫TCPServer.handle_stream()時,你可以使它成爲協程,但__init__()可能不是協程)。

一旦異常被記錄下來,下一步就是解決它。您可以使send_message()read_message()協同程序(在進程中刪除handle_message()回調),也可以使用tornado.gen.Task()從協程中調用協程式樣代碼。我通常建議在任何地方使用協程。

+0

非常感謝 – zonzely