代码之家  ›  专栏  ›  技术社区  ›  jsalonen

如何在Python中通过HTTP从UDP流提供数据服务?

  •  6
  • jsalonen  · 技术社区  · 14 年前

    我目前正致力于通过web公开遗留系统中的数据。我有一个(遗留的)服务器应用程序,它通过UDP发送和接收数据。 软件使用UDP以(近乎)实时的方式(每5-10ms更新一次)向给定的变量集发送顺序更新。因此,我不需要捕获所有的UDP数据——检索最新的更新就足够了。

    为了通过web公开这些数据,我正在考虑构建一个轻量级web服务器,它可以读/写UDP数据并通过HTTP公开这些数据。

    问题如下:

    最好是符合WSGI的解决方案。当然,任何提示都是非常欢迎和感谢!

    3 回复  |  直到 14 年前
        1
  •  4
  •   S.Lott    14 年前

    软件使用UDP以(近乎)实时的方式(每5-10ms更新一次)向给定的变量集发送顺序更新。因此,我不需要捕获所有的UDP数据——检索最新的更新就足够了

    你必须这样做。

    构建一个Python应用程序,收集UDP数据并将其缓存到一个文件中。使用XML、CSV或JSON符号创建文件。

    它作为某种守护进程独立运行。这是你的听众或收藏家。

    完成。

    第二步。

    为此,请使用类似Django的web框架。尽量少写。Django可以提供由侦听器创建的平面文件。

    你完了。再一次。

    有些人认为关系数据库很重要。如果是这样,你可以这样做。即使你已经做完了。

    修改数据集合以创建Django ORM可以查询的数据库。这需要一些学习和调整来获得一个整洁、简单的ORM模型。

    然后编写最终的Django应用程序,为侦听器收集并加载到Django数据库的UDP数据提供服务。

        2
  •  6
  •   Ivo van der Wijk    14 年前
        3
  •  5
  •   MattH    14 年前

    下面是一个使用twisted框架的快速“概念验证”应用程序。这假设传统UDP服务正在侦听localhost:8000和将开始发送UDP数据,以响应包含“Send me data”的数据报。数据是3个32位整数。此外,它将响应端口2080上的“httpget/”。

    你可以从 twistd -noy example.py :

    示例.py

    from twisted.internet import protocol, defer
    from twisted.application import service
    from twisted.python import log
    from twisted.web import resource, server as webserver
    
    import struct
    
    class legacyProtocol(protocol.DatagramProtocol):
        def startProtocol(self):
            self.transport.connect(self.service.legacyHost,self.service.legacyPort)
            self.sendMessage("Send me data")
        def stopProtocol(self):
            # Assume the transport is closed, do any tidying that you need to.
            return
        def datagramReceived(self,datagram,addr):
            # Inspect the datagram payload, do sanity checking.
            try:
                val1, val2, val3 = struct.unpack("!iii",datagram)
            except struct.error, err:
                # Problem unpacking data log and ignore
                log.err()
                return
            self.service.update_data(val1,val2,val3)
        def sendMessage(self,message):
            self.transport.write(message)
    
    class legacyValues(resource.Resource):
        def __init__(self,service):
            resource.Resource.__init__(self)
            self.service=service
            self.putChild("",self)
        def render_GET(self,request):
            data = "\n".join(["<li>%s</li>" % x for x in self.service.get_data()])
            return """<html><head><title>Legacy Data</title>
                <body><h1>Data</h1><ul>
                %s
                </ul></body></html>""" % (data,)
    
    class protocolGatewayService(service.Service):
        def __init__(self,legacyHost,legacyPort):
            self.legacyHost = legacyHost # 
            self.legacyPort = legacyPort
            self.udpListeningPort = None
            self.httpListeningPort = None
            self.lproto = None
            self.reactor = None
            self.data = [1,2,3]
        def startService(self):
            # called by application handling
            if not self.reactor:
                from twisted.internet import reactor
                self.reactor = reactor
            self.reactor.callWhenRunning(self.startStuff)
        def stopService(self):
            # called by application handling
            defers = []
            if self.udpListeningPort:
                defers.append(defer.maybeDeferred(self.udpListeningPort.loseConnection))
            if self.httpListeningPort:
                defers.append(defer.maybeDeferred(self.httpListeningPort.stopListening))
            return defer.DeferredList(defers)
        def startStuff(self):
            # UDP legacy stuff
            proto = legacyProtocol()
            proto.service = self
            self.udpListeningPort = self.reactor.listenUDP(0,proto)
            # Website
            factory = webserver.Site(legacyValues(self))
            self.httpListeningPort = self.reactor.listenTCP(2080,factory)
        def update_data(self,*args):
            self.data[:] = args
        def get_data(self):
            return self.data
    
    application = service.Application('LegacyGateway')
    services = service.IServiceCollection(application)
    s = protocolGatewayService('127.0.0.1',8000)
    s.setServiceParent(services)
    

    事后诸葛亮