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

时间:2010-09-22 09:44:20

标签: python wsgi

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

为了通过网络公开这些数据,我正在考虑构建一个轻量级的Web服务器来读取/写入UDP数据并通过HTTP公开这些数据。

由于我对Python有经验,我正在考虑使用它。

问题如下:如何(持续)从UDP读取数据并使用Python按需TCP / HTTP发送快照?所以基本上,我正在尝试构建一个一种“UDP2HTTP”适配器,用于与传统应用程序连接,以便我不需要触及遗留代码。

更符合WSGI兼容的解决方案。当然,任何提示都非常受欢迎,非常感谢!

3 个答案:

答案 0 :(得分:6)

Twisted在这里非常合适。它支持许多协议(UDP,HTTP),并且它的异步性质使得直接将UDP数据流式传输到HTTP成为可能,而无需使用(阻塞)线程代码将自己射入脚中。它也支持wsgi。

答案 1 :(得分:5)

这是一个使用扭曲框架的快速“概念证明”应用程序。这假设传统UDP服务正在侦听localhost:8000,并将开始发送UDP数据以响应包含“发送数据”的数据报。而且数据是3个32位整数。此外,它将响应端口2080上的“HTTP GET /”。

您可以使用twistd -noy example.py开始:

example.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)

有感

这不是WSGI设计。这样做的想法是使用be来运行这个程序守护进程并在本地IP和apache或类似于代理请求上使用它的http端口。它可以为WSGI重构。这种方式更快,更容易调试。

答案 2 :(得分:3)

  

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

你必须做的就是这个。

第1步。

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

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

将文件写入Apache或其他Web服务器可以轻松下载的目录。明智地选择名称和目录路径,你就完成了。

完成。

如果您想要更漂亮的结果,您可以做更多。你不需要,因为你已经完成了。

第2步。

构建一个Web应用程序,允许某人请求UDP侦听器或收集器累积此数据。

使用像Django这样的Web框架。写得尽量少。 Django可以提供由你的听众创建的平面文件。

你已经完成了。试。

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

第3步。

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

然后编写最终的Django应用程序来提供监听器收集的UDP数据并加载到Django数据库中。