为了账号安全,请及时绑定邮箱和手机立即绑定

Twisted TCP Server无法回送数据

Twisted TCP Server无法回送数据

德玛西亚99 2019-04-19 16:29:33
求熟悉Twisted底层的大神帮助。我的TCP端口服务器一直服务正常,可是一旦加入Redis之后,却不再返回数据了?classPlainTCP(protocol.Protocol):def__init__(self,factory):passdefconnectionMade(self):self.factory.numConnections+=1print"Nr.ofconnections:%d\n"%(self.factory.numConnections)self.transport.write("Helloremote\r\n")defconnectionLost(self,reason):self.factory.numConnections-=1print"Nr.ofconnections:%d\n"%(self.factory.numConnections)defdataReceived(self,data):(self.snrCode,rDat,pDat)=getDataParsed(data)self.transport.write(data)以上代码在远程客户端可以立即获得复制的数据而增加了SQL/Redis数据保存后,事情变得奇怪了。#!/usr/bin/envpythonimporttimeimportbinasciiimporttxredisapifromtwisted.internetimportdeferfromtwisted.internetimportprotocol,reactorfromtwisted.internet.protocolimportFactoryfromtwisted.enterpriseimportadbapifromtwisted.pythonimportlogfromdmpackimportDmpackfromdmdbimportDmdbfromdmconfigimportDmConfdm=Dmpack()conf=DmConf().loadConf()rcs=txredisapi.lazyConnection(password=conf['RedisPassword'])dbpool=adbapi.ConnectionPool("MySQLdb",db=conf['DbName'],user=conf['DbAccount'],\passwd=conf['DbPassword'],host=conf['DbHost'],\use_unicode=True,charset=conf['DbCharset'])defgetDataParsed(data):realtime=Noneperiod=NonesnrCode=dm.snrToAscii(data[2:7])realtime=data[7:167]perid=data[167:-2]return(snrCode,realtime,period)classPlainTCP(protocol.Protocol):def__init__(self,factory):self.factory=factoryself.factory.numConnections=0self.snrCode=Noneself.rData=Noneself.pData=Noneself.err=NonedefconnectionMade(self):self.factory.numConnections+=1print"Nr.ofconnections:%d\n"%(self.factory.numConnections)self.transport.write("Helloremote\r\n")##这里也不返回数据了defconnectionLost(self,reason):self.factory.numConnections-=1print"Nr.ofconnections:%d\n"%(self.factory.numConnections)@defer.inlineCallbacksdefdataReceived(self,data):globaldbpool,rcs(self.snrCode,rDat,pDat)=getDataParsed(data)ifself.snrCode==NoneorrDat==NoneorpDat==None:err="Badformat"else:err="OK"print"err:%s"%(err)###这里可以在终端打印数据self.err=errself.transport.write(self.snrCode)###没有数据返回self.transport.write(self.err)self.transport.write(rDat)self.transport.write(pDat)self.transport.loseConnection()ifself.snrCode!=NoneandrDat!=NoneandpDat!=None:res=yieldself.saveRealTimeData(rcs,rDat)res=yieldself.savePeriodData(dbpool,pDat,conf)print"err2:%s"%(err)###终端有打印@defer.inlineCallbacksdefsaveRealTimeData(self,rc,dat):yieldrc.set(key,val)###自己脑补Key、Valyieldrc.expire(key,30)###可以保存,已经确认@defer.inlineCallbacksdefsavePeriodData(self,rc,dat,conf):query="insert....."###自己脑补SQLyieldrc.runQuery(query)###可以保存,已经确认classPlainTCPFactory(protocol.Factory):defbuildProtocol(self,addr):returnPlainTCP(self)defmain():dmdb=Dmdb()ifnotdmdb.detectDb():print"PleaserunMySQLRDBSfirst."sys.exit()log.startLogging(sys.stdout)reactor.listenTCP(8080,PlainTCPFactory())reactor.run()if__name__=="__main__":main()现象是一旦加入了异步库之后,socket就不在回传了。原始Demo中self.transport.write()没有任何修饰符,所以这应该是同步的。搞不懂异步数据库加入后,为何连connectionMade()这个不相关的句柄中的write()也被失效了。而同时print却是有效的?
查看完整描述

2 回答

?
慕姐4208626

TA贡献1852条经验 获得超7个赞

谢谢大哥关注这个问题。这个是2015年的问题,所以我花了一番力气才看懂我自己的问题,慢慢回想起来。
因为当时我根本没有找到答案,所以只有一步步地反复调整。最后结论是调用异步方式本身不需要yield。因为一旦调用者yield,就调用者也成了生成器了。所以内嵌print也就不执行了。
@defer.inlineCallbacks#这里不需要@defer.inlineCallbacks
defdataReceived(self,data):
res=yieldself.saveRealTimeData(rcs,rDat)#这里不需要yield
@defer.inlineCallbacks
defsaveRealTimeData(self,rc,dat,conf):
yieldrc.set(key,val)#这里需要保留yield
yieldrc.expire(key,conf['RedisDataTTL'])
宗旨:
@defer.inlineCallback修饰的函数里必然有yield;异步函数方法调用者不要再使用异步。
                            
查看完整回答
反对 回复 2019-04-19
  • 2 回答
  • 0 关注
  • 639 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号