开发者

How do I achieve a webpush with data coming from a socket?

开发者 https://www.devze.com 2023-04-10 03:27 出处:网络
Here is my current code: #!/usr/bin/env python from twisted.application import internet, service from twisted.application.service import IServiceMaker, MultiService

Here is my current code:

#!/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)
    r开发者_Python百科eactor.listenUDP(9999, Echo())

    reactor.run()

As you can see, I am trying to call a method in WebPUSH from Echo when data is received. Because I never actually instantiate WebPUSH it doesn't look like I can easily call this method. I tried converting this to use a multiservice method but that didn't seem to work although I am sure I am doing something wrong.

There aren't (as far as I could google) any good examples on multiservice with twisted or atleast one like this.

Any help will be appreciated.


Echo instance needs an instance of WebPUSH protocol to call .logTime().

You need to maintain loggers list, e.g., in main():

...
f.loggers = []
echo = Echo()
echo.loggers = f.loggers
...

Add to it in WebPUSH.connectionMade, remove in WebPUSH.connectionLost:

def connectionMade(self):
    self.factory.loggers.append(self)

def connectionLost(self, reason):
    self.factory.loggers.remove(self)

then in Echo.datagramReceived:

for time_logger in self.loggers:
    time_logger.logTime()


user970077, the example in my blog was meant to be a simplified demo to show how the webpush work. Here is what you are trying to do (incorporating JFB suggestions):

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

And a client to test it (taken from 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()
0

精彩评论

暂无评论...
验证码 换一张
取 消