首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不断监视TCP流提要以获取Python中的数据。

不断监视TCP流提要以获取Python中的数据。
EN

Stack Overflow用户
提问于 2016-12-14 00:26:52
回答 1查看 1.6K关注 0票数 0

我正在用Python3.5编写Python脚本,我有一个主机和端口,我要做的是创建脚本,以便它能够不断地监视提供的主机的数据。数据以xml格式通过TCP流提要分发,标记标记为事件的开始和结束。

因此,我所要做的基本上是监视TCP提要中的新事件,这些事件在xml开始标记和结束标记之间标记,然后检索事件并在脚本中相应地处理它。此外,理想情况下,我需要在毫秒内访问提要中的新数据。

这个提要是一个分发警报的政府提要,这个提要正在流1.naad-adna.pelmore x.com,端口是8080,我想做的是监视这个提要以获取新的警报,然后能够访问警报并在Python中相应地处理它们。提要每分钟发送一次心跳,以指示连接是活动的。

我认为最好的选择是使用Socket,尽管我不知道如何在这个特定的用例中实现它们。我对TCP提要没有多少经验,在我的具体用例下,我无法在网上找到关于如何处理Python中的TCP提要的在线信息,我能够处理xml,但一旦我能够找到如何从TCP提要中提取它的方法。

任何帮助都将不胜感激。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-12-16 03:07:14

在你的问题中有几个技术上的挑战。

首先,连接到服务器并检索数据是一个简单的问题。正如您在下面的connect()中所看到的,这非常简单,只需创建一个套接字(s = socket.socket())并连接它(s.connect(('hostname', port_number)))。

下一个问题是以有用的形式检索数据。套接字本机提供.recv(),但我想要一个类似文件的接口。套接字模块提供了Python特有的方法:.makefile()。(return s.makefile('rb'))

现在我们到了最困难的部分。XML文档通常每个文件存储一个文档,或者每个TCP传输存储一个文档。因此,文档的结尾很容易被文件指示的结束或者Content-Length:头发现。因此,Python中没有一个在一个文件或一个字符串中处理多个XML文档的机制。我写xml_partition()是为了解决这个问题。xml_partition()使用类似文件的对象的数据,并从流中生成每个XML文档。(注意:必须将XML文档按在一起。在最终的>之后不允许使用空格)。

最后,有一个简短的测试程序(alerts()),它连接到流并读取几个XML文档,将每个文档存储到自己的文件中。

这里是一个从Pelmorex的国家警报聚合和传播系统下载紧急警报的程序。

代码语言:javascript
复制
import socket
import xml.etree.ElementTree as ET

def connect():
    'Connect to pelmorex data stream and return a file-like object'
    # Set up the socket
    s = socket.socket()
    s.connect(('streaming1.naad-adna.pelmorex.com', 8080))
    return s.makefile('rb')

# We have to consume the XML data in bits and pieces
# so that we can stop precisely at the boundary between
# streamed XML documents. This function ensures that
# nothing follows a '>' in any XML fragment.
def partition(s, pattern):
    'Consume a file-like object, and yield parts defined by pattern'
    data = s.read(2048)
    while data:
        left, middle, data = data.partition(pattern)
        while left or middle:
            yield left
            yield middle
            left, middle, data = data.partition(pattern)
        data = s.read(2048)

# Split the incoming XML stream into fragments (much smaller
# than an XML document.) The end of each XML document
# is guaranteed to align with the end of a fragment.
# Use an XML parser to determine the actual end of
# a document.  Whenever the parser signals the end
# of an XML document, yield what we have so far and
# start a new parser.
def xml_partition(s):
    'Read multiple XML documents from one data stream'
    parser = None
    for part in partition(s, b'>'):
        if parser is None:
            parser = ET.XMLPullParser(['start', 'end'])
            starts = ends = 0
            xml = []
        xml.append(part)
        parser.feed(part)
        for event, elem in parser.read_events():
            starts += event == "start"
            ends += event == "end"
            if starts == ends > 0:
                # We have reached the end of the XML doc
                parser.close()
                parser = None
                yield b''.join(xml)

# Typical usage:
def alerts():
    for i, xml in enumerate(xml_partition(connect())):
        # The XML is a bytes object that contains the undecoded
        # XML stream. You'll probably want to parse it and
        # somehow display the alert.

        # I'm just saving it to a file.
        with open('alert%d.xml' % i, 'wb') as fp:
            fp.write(xml)
        if i == 3:
            break

def test():
    # A test function that uses multiple XML documents in one
    # file. This avoids the wait for a natural-disaster alert.
    with open('multi.xml', 'rb') as fp:
        print(list(xml_partition(fp)))

alerts()
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41132845

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档