如何在 Python 中通过 HTTP 提供来自 UDP 流的数据?

     2023-03-29     62

关键词:

【中文标题】如何在 Python 中通过 HTTP 提供来自 UDP 流的数据?【英文标题】:How to serve data from UDP stream over HTTP in Python? 【发布时间】:2011-04-15 15:28:25 【问题描述】:

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

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

由于我熟悉 Python,我正在考虑使用它。

问题如下:我如何(持续)从 UDP 读取数据并使用 Python 通过 TCP/HTTP 按需发送快照? 所以基本上,我正在尝试构建一个一种“UDP2HTTP”适配器与旧版应用程序接口,这样我就不需要接触旧版代码。

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

【问题讨论】:

HTTP 中没有“连续”。根据定义。不可能。你在问什么?不知何故不遵循 HTTP 规则而是表现得像 UDP 的 HTTP 协议的奇迹版本? 感谢您的关注。我知道这样的事情不存在。澄清一下:我的问题是试图通过 HTTP 读取 UDP 数据的快照。我不想让 HTTP “连续”(问题也已编辑) 一个好的结构是在 webapp 中以某种方式实现变量的某种模型。 UDP 数据更新该模型(即,webapp 监听它)但不告诉任何 HTTP 事情要更新。从 HTTP 获取的任何内容都只是从这些变量中读取当前状态的快照(并记住禁用生成页面的缓存)。 请注意,虽然上面是一个合理的架构,但它不是答案,因为没有提供代码。 @jsalonen:你的提议听起来像一个协议网关。我已经写了其中的一些。 Twisted 是此类问题的一个非常好的选择(+1 对 Ivo van der Wijk 的回答)。我有几个好奇的问题:以前的值(历史数据)是否重要?您是否需要先请求旧服务器通过 UDP 将数据传输到您的网关? 【参考方案1】:

Twisted 在这里非常适合。它支持许多协议(UDP、HTTP),并且它的异步特性使得可以直接将 UDP 数据流式传输到 HTTP,而无需使用(阻塞)线程代码。它还支持wsgi。

【讨论】:

【参考方案2】:

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

你必须做的是这个。

第 1 步。

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

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

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

完成。

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

第 2 步。

构建一个 Web 应用程序,允许某人请求由 UDP 侦听器或收集器收集的这些数据。

为此使用 Django 之类的 Web 框架。尽量少写。 Django 可以提供您的侦听器创建的平面文件。

你已经完成了。再次。

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

第 3 步。

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

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

【讨论】:

感谢您的详尽回答。但没必要粗鲁,伙计。我很清楚我正在处理一个复杂的问题,谢谢。我同意你的观点,在更长的时间跨度内,持久性、缓存等成为问题。然而,现在,我只需要一个概念验证。在这一点上,任何能证明我如何读取 UDP 数据快照并通过 HTTP 发送它们的工作(甚至是丑陋和 hacky 的代码)就足够了。 请注意,我将问题编辑得更具体! 对不起,这看起来很粗鲁。这个问题——正如最初提出的那样——太模糊了,漏洞百出,无法从表面上认真对待。没有detailsspecifics,隐含的方法不可能奏效。请避免没有详细信息细节的模糊问题。 感谢您修改后的答案,我们非常感谢!我知道我最初的问题不是钻石。如果您觉得缺少细节或细节,请考虑提出要求,而不是发火(我知道我会受到诱惑)——这表明我很乐意在被要求时提供。 另外,我认为这种方法非常合理。一点:使用文件系统存储 UDP 数据听起来不错。但是,我担心我会遇到一些文件锁定问题。但是,是的,您是对的,对于初始原型来说可能就足够了(稍后我们可以切换到数据库)。【参考方案3】:

这是一个使用扭曲框架的快速“概念验证”应用。这假设旧 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 设计。这样做的想法是运行这个程序守护进程,并让它的 http 端口在本地 IP 和 apache 上或类似于代理请求。它可以针对 WSGI 进行重构。这种方式敲起来更快,更容易调试。

【讨论】:

非常感谢您用实际代码回答。我偶然发现了 twisted 很多次,但实际上并不知道它有多难使用。此代码提供了一个概念验证代码,我可以将其作为起点进行传播和使用。 不客气。我认为 twisted 的一个缺点是学习曲线陡峭,并且在你有足够的工作概念开始迭代改进之前可能会有很大的努力障碍。

如何在angularjs中通过ajax显示来自url的json数组

】如何在angularjs中通过ajax显示来自url的json数组【英文标题】:Howtodisplayjsonarraycomingfromurlthroughajaxinangularjs【发布时间】:2018-06-1219:51:17【问题描述】:我有一个来自url的json数组:http://blahblahblah.com/company/all,像这样:在angularjs... 查看详情

在 Swift2 中通过 HTTP2 与 APNS 服务器通信

...ft2【发布时间】:2015-11-2322:36:49【问题描述】:有谁知道如何使用Apple在WWDC2015会议中引入的新APNS提供程序API?对于我的测试,我使用了PushMeBaby(来自github的开源推送服务器)。但是这个小应用程序将来不会再工作了。有人用Swi... 查看详情

如何在 SwiftUI 中通过 ViewModel 传播模型更改?

】如何在SwiftUI中通过ViewModel传播模型更改?【英文标题】:HowtopropagateModelchangesthroughViewModelinSwiftUI?【发布时间】:2020-09-1023:52:36【问题描述】:我试图了解SwiftUI中的MVVM模式,但我不完全了解ViewModel如何侦听和传播来自Model对象... 查看详情

如何压缩 JSONObject 在 Android 中通过 Http 发送它?

】如何压缩JSONObject在Android中通过Http发送它?【英文标题】:HowtoCompressaJSONObjectsenditoverHttpinAndroid?【发布时间】:2012-07-0907:25:54【问题描述】:我使用thisexample中的代码从Androidclient向我的网络服务器发送JSONObject。此处重现代码im... 查看详情

如何在python中通过引用调用静态方法[重复]

】如何在python中通过引用调用静态方法[重复]【英文标题】:Howtocallstaticmethodbyreferenceinpython[duplicate]【发布时间】:2017-07-0514:17:51【问题描述】:请看下面的例子:classMyClass(object):@staticmethoddef__myStaticMethod(someArgs):passMY_SPECIAL_METHOD... 查看详情

如何在 ruby​​ 中通过 SSL 调用 HTTP POST 方法?

】如何在ruby​​中通过SSL调用HTTPPOST方法?【英文标题】:HowtoinvokeHTTPPOSTmethodoverSSLinruby?【发布时间】:2012-06-1018:26:12【问题描述】:这是使用curl的请求:curl-XPOST-Hcontent-type:application/json-d"\\"credentials\\":\\"username\\":\\"username\\",\\"... 查看详情

如何在 Go 中通过 http:// 发出仅 HTTP2 的请求?

】如何在Go中通过http://发出仅HTTP2的请求?【英文标题】:HowdoImakeaHTTP2-onlyrequestoverhttp://inGo?【发布时间】:2016-03-3119:26:26【问题描述】:我正在使用Go1.6,并希望通过http://发出仅HTTP2请求。目前尝试这样做会导致:负责人http://lo... 查看详情

如何在python中通过命令行给出元组

】如何在python中通过命令行给出元组【英文标题】:howtogivetupleviacommandlineinpython【发布时间】:2021-01-1900:58:24【问题描述】:我必须通过命令行输入一些参数。例如tileGridSize、clipLimit等通过命令行。这就是我的代码的样子;#!/usr... 查看详情

如何在 UTF-8 中通过 http post 发送字符串

】如何在UTF-8中通过httppost发送字符串【英文标题】:howtosendstringbyhttppostinUTF-8【发布时间】:2013-03-1012:04:46【问题描述】:我尝试发送字符串“Приветмир!”Stringlink=POST_URL;HttpClienthttpclient=newDefaultHttpClient();HttpPosthttppost=newHttpP... 查看详情

使用请求(不是 GET)在 Python 中通过 Post HTTP Request 下载 PDF

】使用请求(不是GET)在Python中通过PostHTTPRequest下载PDF【英文标题】:DownloadPDFviaPostHTTPRequestinPythonusingRequest(notGET)【发布时间】:2022-01-1108:26:11【问题描述】:我的问题与许多其他问题略有不同。我正在做一个带有下载PDF(不是... 查看详情

如何在 Qt5 中通过 http 连接到 PUSH 服务器

】如何在Qt5中通过http连接到PUSH服务器【英文标题】:HowtoconnecttoaPUSHserverviahttpinQt5【发布时间】:2014-06-0317:23:56【问题描述】:查看QNetworkAccessManager我没有看到任何与“推送”相关的内容。http://qt-project.org/doc/qt-5/qnetworkaccessmanage... 查看详情

如何使用 Dio 或 http 在 Flutter 中通过 GET 请求发送参数

】如何使用Dio或http在Flutter中通过GET请求发送参数【英文标题】:HowtosendparameterswithGETrequestinFlutterusingDioorhttp【发布时间】:2020-11-2903:46:21【问题描述】:我正在尝试使用一些参数向后端服务器发送GET请求,但我收到了错误:DioEr... 查看详情

如何在 ASP.NET MVC3 中通过 HTTPS 提供静态文件(在 ~/Content 中)

】如何在ASP.NETMVC3中通过HTTPS提供静态文件(在~/Content中)【英文标题】:HowtoServeStaticFiles(in~/Content)ViaHTTPSinASP.NETMVC3【发布时间】:2013-09-1816:39:21【问题描述】:我有一个ASP.NETMVC3应用程序,我刚刚添加了一个区域。区域内的链... 查看详情

在 Python 中通过 ElementTree 解析 xml 时如何保留命名空间

】在Python中通过ElementTree解析xml时如何保留命名空间【英文标题】:HowtopreservenamespaceswhenparsingxmlviaElementTreeinPython【发布时间】:2019-06-2315:48:04【问题描述】:假设我有以下想要使用Python的ElementTree修改的XML:<rootxmlns:prefix="URI"&... 查看详情

如何在 Ruby 中通过引用传递?

】如何在Ruby中通过引用传递?【英文标题】:HowtopassbyreferenceinRuby?【发布时间】:2017-01-0508:19:14【问题描述】:目前我正在Ruby中开发一个Watcher类,除其他外,它能够找到切换信号的周期持续时间。这通常相当简单,但我面临的... 查看详情

如何在 Python 中通过身份验证从 URL 获取 CSV 文件

】如何在Python中通过身份验证从URL获取CSV文件【英文标题】:HowtogetCSVfilefromURLwithauthenticationinPython【发布时间】:2022-01-1107:13:56【问题描述】:我正在做一个关于physionet的项目。我也有physionet证书。我正在尝试将csv文件直接放入... 查看详情

如何在python中通过正则表达式获取dict值

】如何在python中通过正则表达式获取dict值【英文标题】:howtogetdictvaluebyregexinpython【发布时间】:2013-08-0413:05:39【问题描述】:dict1=\'s1\':[1,2,3],\'s2\':[4,5,6],\'a\':[7,8,9],\'s3\':[10,11]我怎样才能得到\'s\'键的所有值?比如dict1[\'s*\']得... 查看详情

如何在python中通过多种格式格式化日期字符串

】如何在python中通过多种格式格式化日期字符串【英文标题】:Howtoformatdatestringviamultipleformatsinpython【发布时间】:2014-06-2804:02:41【问题描述】:我有三种日期格式:YYYY-MM-DD、DD.MM.YYYY、DD/MM/YYYY。是否可以验证和解析2014-05-18或18.... 查看详情