求熟悉Twisted底层的大神帮助。
我的TCP端口服务器一直服务正常,可是一旦加入Redis之后,却不再返回数据了?
class PlainTCP(protocol.Protocol):
def __init__(self, factory):
pass
def connectionMade(self):
self.factory.numConnections += 1
print "Nr. of connections: %d\n" %(self.factory.numConnections)
self.transport.write("Hello remote\r\n")
def connectionLost(self, reason):
self.factory.numConnections -= 1
print "Nr. of connections: %d\n" %(self.factory.numConnections)
def dataReceived(self, data):
(self.snrCode,rDat,pDat) = getDataParsed(data)
self.transport.write(data)
以上代码在远程客户端可以立即获得复制的数据
而增加了SQL/Redis数据保存后,事情变得奇怪了。
#!/usr/bin/env python
import time
import binascii
import txredisapi
from twisted.internet import defer
from twisted.internet import protocol, reactor
from twisted.internet.protocol import Factory
from twisted.enterprise import adbapi
from twisted.python import log
from dmpack import Dmpack
from dmdb import Dmdb
from dmconfig import DmConf
dm = 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'])
def getDataParsed(data):
realtime = None
period = None
snrCode = dm.snrToAscii(data[2:7])
realtime = data[7:167]
perid = data[167:-2]
return (snrCode, realtime, period)
class PlainTCP(protocol.Protocol):
def __init__(self, factory):
self.factory = factory
self.factory.numConnections = 0
self.snrCode = None
self.rData = None
self.pData = None
self.err = None
def connectionMade(self):
self.factory.numConnections += 1
print "Nr. of connections: %d\n" %(self.factory.numConnections)
self.transport.write("Hello remote\r\n") ##这里也不返回数据了
def connectionLost(self, reason):
self.factory.numConnections -= 1
print "Nr. of connections: %d\n" %(self.factory.numConnections)
@defer.inlineCallbacks
def dataReceived(self, data):
global dbpool, rcs
(self.snrCode,rDat,pDat) = getDataParsed(data)
if self.snrCode == None or rDat == None or pDat == None:
err = "Bad format"
else:
err = "OK"
print "err:%s"%(err) ### 这里可以在终端打印数据
self.err = err
self.transport.write(self.snrCode) ### 没有数据返回
self.transport.write(self.err)
self.transport.write(rDat)
self.transport.write(pDat)
self.transport.loseConnection()
if self.snrCode != None and rDat != None and pDat != None:
res = yield self.saveRealTimeData(rcs, rDat)
res = yield self.savePeriodData(dbpool, pDat, conf)
print "err2:%s"%(err) ### 终端有打印
@defer.inlineCallbacks
def saveRealTimeData(self, rc, dat):
yield rc.set(key,val) ### 自己脑补Key、Val
yield rc.expire(key,30) ### 可以保存,已经确认
@defer.inlineCallbacks
def savePeriodData(self,rc,dat,conf):
query = "insert....." ### 自己脑补SQL
yield rc.runQuery(query) ### 可以保存,已经确认
class PlainTCPFactory(protocol.Factory):
def buildProtocol(self, addr):
return PlainTCP(self)
def main():
dmdb = Dmdb()
if not dmdb.detectDb():
print "Please run MySQL RDBS first."
sys.exit()
log.startLogging(sys.stdout)
reactor.listenTCP(8080, PlainTCPFactory())
reactor.run()
if __name__ == "__main__":
main()
现象是一旦加入了异步库之后,socket就不在回传了。原始Demo中self.transport.write()没有任何修饰符,所以这应该是同步的。搞不懂异步数据库加入后,为何连connectionMade()这个不相关的句柄中的write()也被失效了。而同时print却是有效的?
谢谢大哥关注这个问题。这个是2015年的问题,所以我花了一番力气才看懂我自己的问题,慢慢回想起来。
因为当时我根本没有找到答案,所以只有一步步地反复调整。最后结论是调用异步方式本身不需要yield。因为一旦调用者yield,就调用者也成了生成器了。所以内嵌print也就不执行了。
宗旨:
@defer.inlineCallback修饰的函数里必然有yield; 异步函数方法调用者不要再使用异步。