如何在Python中接收UDP数据包而不丢弃

时间:2014-10-24 19:23:07

标签: python sockets udp mpeg2-ts

我正在编写简单的软件来解析MPEG-TS流以检查CC(cointinuity计数器)以查看是否有任何数据包被丢弃。当我对文件运行我的脚本时,它可以完美地运行。但是当在UDP流上使用它时,它会显示丢失(未经其他软件确认):

这很简单:

while True:
    received = sock.recv(7 * 188)
    parsepacket(received)

为了清楚起见,我省略了parsepacket功能。它只是使用bitstring来逐位分析数据包。

根据我的理解,当我运行parsepacket函数时,其他UDP数据包被忽略,因为我没有足够快地执行sock.recv(在5 Mbps流上它应该解析大约500个数据包)。< / p>

我尝试使用sock.makefile,但没有运气。我得到了相同的结果。

我的想法是让接收线程在后台运行,另一个线程不断解析它收到的内容。但老实说,我不知道怎么做(除了把它全部放在内存中会很快耗尽)。

2 个答案:

答案 0 :(得分:1)

如果没有看到您的脚本,或者您实际上是在做什么,我们将无法为您提供帮助。但是,如果您使用Python的twisted库,这是微不足道的。这是一个简单的例子,取自他们的examples page

from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor


class MulticastPingPong(DatagramProtocol):

    def startProtocol(self):
        """
        Called after protocol has started listening.
        """
        # Set the TTL>1 so multicast will cross router hops:
        self.transport.setTTL(5)
        # Join a specific multicast group:
        self.transport.joinGroup("228.0.0.5")

    def datagramReceived(self, datagram, address):
        print "Datagram %s received from %s" % (repr(datagram), repr(address))
        if datagram == "Client: Ping":
            # Rather than replying to the group multicast address, we send the
            # reply directly (unicast) to the originating port:
            self.transport.write("Server: Pong", address)


# We use listenMultiple=True so that we can run MulticastServer.py and
# MulticastClient.py on same machine:
reactor.listenMulticast(8005, MulticastPingPong(),
                        listenMultiple=True)
reactor.run()

您可以解析def datagramReceived函数中的每个数据包。

答案 1 :(得分:0)

  

我的想法是让接收线程在后台和另一个中运行   线程不断解析它收到的内容。但说实话,我没有   想法如何(除了把它全部放在内存中会非常耗尽   快)。

这可能是最好的方法,因为当您的python代码忙于解析早期的数据包时,套接字的传入UDP数据包缓冲区(位于TCP堆栈中)将不会填满。

通过生成第二个线程并使用synchronized FIFO Queue将数据从网络处理线程发送到数据包解析线程,您可以非常轻松地实现该模式。一旦您的网络线程读取数据包,它就会将数据包放入队列,然后返回读取下一个数据包。同时,你的处理线程在同一个Queue上调用get()的循环中运行,只有当get()返回一个数据包供它处理时才会唤醒。

要注意的一件事是,如果您的网络线程持续接收数据包的速度超过处理线程可以解析它们的速度,会发生什么。在这种情况下,您的队列将无限制地变大(最终耗尽所有机器的RAM),或者(如果您为队列设置了最大大小),队列将达到其最大大小并且put()将提出一个完整的例外。