这是我目前的代码:
#!/usr/bin/env python
from twisted.application import internet, service
from twisted.application.service import IServiceMaker, MultiService
from twisted.protocols import basic
from twisted.internet import reactor, protocol, defer
from twisted.internet.protocol import DatagramProtocol
import datetime
class WebPUSH(basic.LineReceiver):
logTemplate = '''
<script type="text/javascript">
pushHandler.addLi('%s')
</script>
'''
def __init__(self):
self.gotRequest = False
def lineReceived(self, line):
if not self.gotRequest:
self.startResponse()
self.gotRequest = True
def startResponse(self):
self.sendLine('HTTP/1.1 200 OK')
self.sendLine('Content-Type: text/html; charset=utf-8')
self.sendLine('')
f = open('index.html', 'r')
self.transport.write( ''.join(f.read()) )
f.close()
self.logTime()
def logTime(self):
self.sendLine( self.logTemplate % datetime.datetime.now() )
#reactor.callLater(2, self.logTime)
class Echo(DatagramProtocol):
def datagramReceived(self, data, (host, port)):
WebPUSH.logTime()
print "received %r from %s:%d" % (data, host, port)
self.transport.write(data, (host, port))
if __name__ == '__main__':
f = protocol.ServerFactory()
f.protocol = WebPUSH
reactor.listenTCP(8080, f)
reactor.listenUDP(9999, Echo())
reactor.run()
正如您所看到的,我正在尝试在收到数据时从Echo调用WebPUSH中的方法。因为我从未实际实例化WebPUSH,所以看起来我不能轻易调用此方法。我尝试将其转换为使用多服务方法,但这似乎不起作用,虽然我确信我做错了。
对于像这样的扭曲或至少这样的多服务,没有(据我可以谷歌)任何好的例子。
任何帮助将不胜感激。
答案 0 :(得分:0)
Echo
实例需要WebPUSH
协议实例才能调用.logTime()
。
您需要维护loggers
列表,例如main()
:
...
f.loggers = []
echo = Echo()
echo.loggers = f.loggers
...
在WebPUSH.connectionMade
中添加,在WebPUSH.connectionLost
中删除:
def connectionMade(self):
self.factory.loggers.append(self)
def connectionLost(self, reason):
self.factory.loggers.remove(self)
然后在Echo.datagramReceived
:
for time_logger in self.loggers:
time_logger.logTime()
答案 1 :(得分:0)
user970077,我博客中的示例是一个简化的演示,用于展示webpush的工作原理。以下是您要做的事情(纳入JFB建议):
#!/usr/bin/env python
from twisted.protocols import basic
from twisted.internet import reactor, protocol, defer
import datetime
class WebPUSH(basic.LineReceiver):
logTemplate = '''
<script type="text/javascript">
pushHandler.addLi('%s')
</script>
'''
def connectionMade(self):
self.factory.listeners.append(self)
self.startResponse()
def connectionLost(self, reason):
self.factory.listeners.remove(self)
def lineReceived(self, line):
self.sendLine( self.logTemplate % line )
def startResponse(self):
self.sendLine('HTTP/1.1 200 OK')
self.sendLine('Content-Type: text/html; charset=utf-8')
self.sendLine('')
with open('index.html', 'r') as f:
self.transport.write( ''.join(f.read()) )
class WebPushFactory(protocol.ServerFactory):
protocol = WebPUSH
def __init__(self):
self.listeners = []
class Echo(protocol.DatagramProtocol):
def __init__(self, listeners):
self.listeners = listeners
def datagramReceived(self, data, (host, port)):
msg = '[%s:%s] %s' % (host, port, data)
for listener in self.listeners:
# udp is not necessarily line-oriented
# so we can:
# 1) feed dataReceived and wait until the line
# delimiter arrives in an udp package
# triggering lineReceived:
#listener.dataReceived( msg )
# or 2) fake a line by calling lineReceived direclty:
listener.lineReceived( msg )
print msg
self.transport.write(data, (host, port))
if __name__ == '__main__':
web = WebPushFactory()
reactor.listenTCP(8080, web)
reactor.listenUDP(9999, Echo(web.listeners))
reactor.run()
一个测试它的客户端(取自UDP client and server with Twisted Python):
#!/usr/bin/env python
from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor
from twisted.internet.task import LoopingCall
import sys, time
class HeartbeatSender(DatagramProtocol):
def __init__(self, name, host, port):
self.name = name
self.loopObj = None
self.host = host
self.port = port
def startProtocol(self):
# Called when transport is connected
# I am ready to send heart beats
self.loopObj = LoopingCall(self.sendHeartBeat)
self.loopObj.start(2, now=False)
def stopProtocol(self):
"Called after all transport is teared down"
pass
def datagramReceived(self, data, (host, port)):
print "received %r from %s:%d" % (data, host, port)
def sendHeartBeat(self):
self.transport.write(self.name, (self.host, self.port))
if __name__ == '__main__':
sender = HeartbeatSender("sender", "127.0.0.1", 9999)
reactor.listenMulticast(9998, sender, listenMultiple=True)
reactor.run()