【问题标题】:Socket lose part of message in UDP套接字在 UDP 中丢失部分消息
【发布时间】:2018-04-02 05:02:18
【问题描述】:

我正在尝试使用 Python 2.7 通过 UDP 套接字发送图像帧,我尝试发送的当前帧是 921600 字节 (640 x 480)。并且UDP消息的缓冲区限制为65507字节,所以我需要拆分消息,这是我的做法。

来自client.py

image_string = frame.tostring()              # frame is an multi-d numpy array
message_size = len(image_string)
sock.sendto(str(message_size), (HOST, PORT)) # First send the size

for i in xrange(0, message_size, 65507):     # Split it and send
    sock.sendto(image_string[i:i + 65507], (HOST, PORT))

sock.sendto("\n", (HOST, PORT))              # Mark the end to avoid hanging.

这是我在server.py 中收到它的方式,我插入了一些打印件进行调试。

image_string = ""

data, addr = sock.recvfrom(1024) # recieve image size
message_size = int(data)
print "Incoming image with size: " + data

for i in xrange(0, message_size, 65507):
    data, addr = sock.recvfrom(65507)
    image_string += data.strip()
    print "received part, image is now:", len(image_string)

print "End of image"

因此,我正在以与发送消息相同的方式阅读消息,它在理论上可以检查,但在实践中却没有。可能是因为客户端完成发送后一些数据包丢失 - 服务器仍然卡在尝试读取(被阻止)。

我知道 UDP 不可靠且难以使用,但是我读到 UDP 用于许多视频流应用程序,所以我相信应该有解决这个问题的方法,但我找不到。

感谢所有帮助,谢谢。

Edit1:我怀疑丢包是问题的原因,是因为每次我运行测试时,在服务器挂起之前我已经发送了不同大小的图像。

Edit2:我忘了提到我在分区时尝试了不同大小的块,1024 和 500 字节没有区别(921600 中丢失了 5-20 字节)。但我应该提一下,我正在从 localhost 发送和接收,这已经提供了最小的错误。

【问题讨论】:

  • “我读到很多视频流应用都使用了UDP,所以我相信应该有解决这个问题的办法” - UDP用于视频的实时传输和音频,当丢包比接收迟到更好时。但在这种情况下,使用可以处理数据包丢失的适当编解码器。看起来您需要可靠的传输,并且没有实时要求。在这种情况下,您应该使用 TCP。
  • @SteffenUllrich 我意识到,当我自己尝试让它工作时。我还应该说,划分为块会使 UDP 中的传输非常慢,根据我的经验,TCP sendall 要快得多(我实际上是在制作实时流)。确实我无法处理数据包丢失,特别是因为数据包是一串 numpy 数组,我不知道如何在服务器端恢复(模仿)丢失的数据。或许我应该再问一个关于处理丢包的问题,​​谢谢。
  • 这个问题的答案将是使用 TCP!要么就是这样,要么你实现了类似 TCP 的东西。
  • @eandersson 感谢您的建议,但很明显,我自己实现的任何东西都会比本机协议慢,除非我花大量时间在它上面,这不是我的愿望。

标签: python python-2.7 sockets server


【解决方案1】:

我知道 UDP 不可靠且难以使用,但是我读到 UDP 用于许多视频流应用程序,所以我相信应该有解决这个问题的方法,但我找不到。

那些家伙可以。他们设计自己的协议时知道数据可能会丢失(甚至相反,可能会多次到达),可能会乱序到达,而他们的协议/应用程序期望这样。

您不能简单地将数据切成小块并使用 UDP 发送。您必须以一种方式形成每条单独的信息,使它们中的每一条都有其自身的含义。如果它是一个“流”,它必须包含该特定数据在流中的位置,并且当您的应用程序接收到它时,它将知道是否可以处理给定的数据,它已经过时(到达太晚,或已经到达),它应该被搁置一旁,并希望一些前面的部分会到达,可能本身无法使用,应用程序应该直接向发送者发送请求,以便再次同步。

在传输图像或一系列图像的情况下,您可以发送数据的偏移量,并在接收到某些内容时简单地将给定的偏移量覆盖一个固定大小的缓冲区(可以容纳一个完整的图像),然后渲染结果。然后缓冲区将始终包含一些图像,至少是几个图像的某种混合 - 或者在非常幸运的情况下,一个单一的“真实”图像。

编辑:“评估”如何处理包的示例:除了偏移量之外,图像的编号(“时间戳”)也可能存在,然后应用程序可以避免覆盖图像的较新部分带有旧的东西 - 过去(重新)出现的一些数据包是否出于任何原因。

【讨论】:

    【解决方案2】:

    为什么要使用最大缓冲区限制?您可以通过 UDP 可靠发送的最大有效负载是 534 字节。发送更多可能会导致碎片。如果您担心数据丢失,请使用 TCP。

    【讨论】:

    • 这没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方留下评论。 - From Review
    • @FirstZero 我明确提到了用于可靠传输的字节大小:)
    • 没有可以通过 UDP 可靠发送的数据包大小 -- 任何大小的数据包都可能被丢弃。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多