【问题标题】:How do I achieve a webpush with data coming from a socket?如何使用来自套接字的数据实现 webpush?
【发布时间】:2011-10-03 22:20:49
【问题描述】:

这是我当前的代码:

#!/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,所以看起来我不能轻易地调用这个方法。我尝试将其转换为使用多服务方法,但这似乎不起作用,尽管我确信我做错了什么。

没有(据我所知)任何关于多服务的好例子,比如这样的扭曲或至少一个。

任何帮助将不胜感激。

【问题讨论】:

  • 至少对我来说还不清楚你在这里实际想要完成什么。看起来您有一个 UDP 协议,它有点连接到 HTTP 实现的一半,并且您对类和实例之间的区别有点困惑。我不明白MultiService 与任何事情有什么关系。您是否正在尝试制作一个长轮询 Web 服务器?

标签: python http sockets streaming twisted


【解决方案1】:

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()

【讨论】:

    【解决方案2】:

    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()
    

    【讨论】:

      猜你喜欢
      • 2016-08-31
      • 1970-01-01
      • 1970-01-01
      • 2017-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多