reactor模式总是由事件驱动方法,一个问题是:当一个方法被驱动,我应该调用哪个处理函数?另一个问题是:reactor模式总是被动的激活某个方法,然后被动的激活处理函数,那么我们现在想主动调用某个方法,应该怎么调用,时机在哪里?这两个问题很困扰,反复研究官方文档,找到了些眉目。
对比boost asio的proactor模式,proactor总是主动的调用某个方法,然后注册一个回调处理函数。当这个方法执行完毕,就回调处理函数。除了需要管理缓冲和套接字,感觉比reactor好驾驭
注意两个细节
1。getattr方法,查找处理函数,就像查找字符串一样,利用getattr就能实现一个处理函数分派器。根据当前状态查找对应的处理函数,然后调用。
2。注意调用Smtp方法的时机,当connectTCP完成,注册一个回调函数,twisted会把Smtp的实例传进处理函数,这里就是主动调用Smtp的方法的时机,
这里的关键是管理Smtp的状态,因为这些调用总是异步的,一种简单方法是使用同步锁,需要保持当前的状态时,上锁,但这又跟异步的思想违背,同步导致低效
另一个方法是:MedhodA->handleA->MedhodB->handleB->.......形成一条回调链,这方法适用一系列固定的方法序列(可能这个方法用在 twisted上是比较自然的),但缺乏灵活,如果需要另一个序列,则要重新定义新的protocol,也不好修改
用那个方法?按实际决定吧,继续研究。。。。
from twisted.protocols.basic import LineOnlyReceiver
from _codecs import encode
from twisted.internet.protocol import ClientCreator,defer
from twisted.internet import reactor,threads
class Smtp(LineOnlyReceiver):
def test_entrance(self,msg):
print(msg)
def connectionMade(self):
self.state = "welcome"
def putCMD(self,CMD):def
self.sendLine(encode(CMD+'\r\n'))
def handle_welcome(self,*args):
print (args)
def HELO(self,user):
self.state='HELO'
self.putCMD('HELO ' + user)
def handle_helo(self,*args):
print(args)
self.state=None
def QUIt(self):
self.state = 'QUIT'
self.putCMD('QUIT')
def handle_quit(self,*args):
print(args)
reactor.stop()
def lineReceived(self, line):
command = self.state.lower()
self._dispatch(command,line)
def _dispatch(self, command, *args):
method = getattr(self, 'handle_'+command)
if method is not None:
method(*args)
else:
raise AttributeError("no this mothod")
def connectHandel(smtpObject):
#smtpObject是Smtp的一个实例
print(type(smtpObject))
assert(isinstance(smtpObject,Smtp))
smtpObject.test_entrance("entered!")#这里就是调用Smtp的方法的入口!
def on_error(reason):
print(type(reason))
print(reason)
creator = ClientCreator(reactor, Smtp)
d=creator.connectTCP("smtp.126.com",25)
d.addErrback(on_error)
d.addCallback(connectHandel)#连接处理函数,会把Smtp的实例作为参数传过去
d.addErrback(on_error)#错误处理函数,会把错误的原因(twisted.python.failure.Failure实例)传过去
reactor.run()