【问题标题】:How to avoid UDP socket transfers limits?如何避免 UDP 套接字传输限制?
【发布时间】:2010-09-26 11:32:26
【问题描述】:

我编写了一个小程序,通过 udp 套接字连接将文件从客户端发送到服务器.. 程序正常工作,但如果我传输的文件大于 8192 kb,则流停止并且我收到的文件已损坏.. 如何避免这种限制?

server.py

host = ...
port = ...
filename = ...

buf = 2048
addr = (host, port)

UDPSock = socket(AF_INET, SOCK_DGRAM)
UDPSock.bind(addr)

f = open(filename, 'wb')

block,addr = UDPSock.recvfrom(buf)
while block:
    if(block == "!END"): # I put "!END" to interrupt the listener
        break
    f.write(block)
    block,addr = UDPSock.recvfrom(buf)

f.close()
UDPSock.close()

client.py

host = ...
port = ...
filename = ...

buf = 2048
addr = (host, port)

UDPSock = socket(AF_INET, SOCK_DGRAM)

f = open(filename, 'rb')

block = f.read(buf)
while block:
        UDPSock.sendto(block, addr)
        block = f.read(buf)

UDPSock.sendto("!END", addr)
f.close()
UDPSock.close()

【问题讨论】:

  • 请说明为什么需要使用UDP;如果你愿意,可以问一个单独的问题。使用 UDP 进行文件传输不必要地复杂,在高延迟链接上高效执行非常复杂。
  • 我需要使用 UDP,因为我的项目是在我的本地网络中创建一个 voip,所以我需要非常快速的数据包传输,我不需要高质量的音频并且我在本地工作,所以我不需要'没有高延迟链接..但现在我正在测试主机之间设置配置调整块大小和传输之间的睡眠时间..我正在寻找最佳折衷速度/质量(我发布了另一个问题但没有答案..stackoverflow.com/questions/3789675/…)
  • UDP 和 TCP 不是相互排斥的,应用程序可以将两者用于不同的目的。例如,许多游戏都使用两者。如果需要,您还可以使用多个 TCP 连接。
  • 这是一个家庭作业问题吗?您坚持使用 UDP 听起来像是人为的限制。
  • 只是在网上冲浪我读到 TCP 对于实时数据传输来说太慢了。我犯规了?

标签: sockets udp limit transfer


【解决方案1】:

在发送 t 之前,您必须将文件拆分成更小的块。 8192 相当大,我认为通过 Internet 发送它可能会遇到麻烦,我会坚持使用 512 字节。还请记住,UDP 不是一个可靠的协议,即您的某些数据包可能根本不来。我建议使用 TCP 传输文件,它解决了您在使用 UDP 时必须自己解决的所有问题。

【讨论】:

  • 谢谢,我需要使用 UDP .. 如何分块文件?在我的示例中,我读取了 2kb 并发送了这个数据包。这不是制作数据包的方法吗?我需要为每个数据包打开一个连接吗?
  • 不,您不需要为每个数据包打开一个新连接。考虑到您 100% 确定 !END 不会出现在您发送的数据中,您在更新的示例中使用它的方式应该可以工作。
【解决方案2】:

您还没有解释为什么必须使用 UDP - 它根本不是为大量数据传输而设计的,因为它没有任何(简单的)拥塞管理。

如果您发送 VoIP,那么什么时候不只是实时传输,而不是“尽可能快”?

FWIW,典型的 VoIP 系统将数据打包成 20 毫秒左右的块。因此,如果您使用像 GSM 这样需要 13 kbps 的语音编解码器,您只需将每个数据包分成 260 位(约 32 字节),然后每 0.02 秒发送一次。

【讨论】:

  • 谢谢..这些是我正在寻找的信息..我确信 UDP 是进行实时数据传输的唯一方法..所以我可以使用 TCP 连接而无需实时转账问题
  • 不,如果您想要以正常音频速率实时传输 VoIP 数据,您应该使用 UDP。尤其是 RTP 协议,这是真正的 VoIP 系统使用并通过 UDP 运行的协议。您不应该做的是“尽快”使用 UDP 进行批量传输。
【解决方案3】:

使用 tcp 传输大文件可能是个好主意。

您需要对 udp 执行的操作是将文件拆分成块、处理丢失的块、重试和乱序 pkts。

使用 tcp 你不需要。

【讨论】:

  • 谢谢,我需要使用 UDP .. 如何分块文件?在我的示例中,我读取了 2kb 并发送了这个数据包。这不是制作数据包的方法吗?我需要为每个数据包打开一个连接吗?
  • 如果你想使用UDP,那么你就浪费了很多精力。您实际上需要复制 TCP 所做的事情。为了在高延迟链路上实现不错的传输速率,您需要在之前的内容被确认之前发送更多数据,并记住哪些已经确认,哪些没有。您需要容忍丢失的数据包和乱序的数据包。您需要对数据包进行适当的校验(IP 校验和太弱,无法在传输大/重要数据时避免损坏)和其他各种事情。
【解决方案4】:

您达到的 8192 限制对应于 Windows 中套接字发送和接收缓冲区的大小。我很惊讶它完全适用于 1460 字节以上的文件,因为数据包在被放到网络上之前会被截断到那个或更小。您是否在同一主机内进行测试?

当您弄清楚这一点后,您将不得不处理不止一次或根本不按顺序到达的数据包。你确定你必须使用UDP吗?它不适合初学者。

【讨论】:

  • 我正在使用 UDP,因为它仅用于测试目的。我解决了我的问题,将不同数据包之间的睡眠时间按 0.0001 秒的顺序放置。我不担心丢失数据包因为我发送媒体文件,所以我可以容忍数据包丢失并且我不需要高质量.. 对于 4mb 的文件,我发送 2000 个数据包,我在两个不同的主机之间以 1000 kb/s 的速度接收 1996 个数据包文件的最佳质量
【解决方案5】:

您所做的只是重新实现 TCP 非常糟糕,使用 UDP 的唯一原因应该是一对多传输或持续运行的企业服务总线中间件。

在用尽现有定义良好的传输之后,应将 UDP 作为不可靠的单向传输视为一个非常小的利基解决方案。

注意互联网上的大数据传输,小写“I”仍然是唯一可靠的,您通常应该添加应用程序框架和有效负载验证。

我建议研究现有的文件传输技术,例如 FSP (UDP)、HTTP (TCP)、SPDY(优化的 HTTP),或者与您自己在现有的面向消息的之上滚动的其他通信集成-JBoss0MQ等中间件系统。

【讨论】:

    【解决方案6】:

    如果非要使用UDP,请看http://en.wikipedia.org/wiki/Trivial_File_Transfer_Protocol

    它定义了一个可靠的协议。如果您的上下文允许 TCP,您应该更喜欢使用它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-26
      • 1970-01-01
      • 2011-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多