【问题标题】:socket UDP recvfrom not working for large packets even if buffer given is enough on LINUX即使在 LINUX 上给定的缓冲区足够,socket UDP recvfrom 也不能用于大数据包
【发布时间】:2012-07-06 13:51:41
【问题描述】:

我正在调用有效地址的 recvfrom api,我试图读取大小为 9600 字节的数据,我提供的缓冲区大小为 12KB,我什至没有收到选择读取事件。 甚至强硬推荐的 MTU 大小是 1.5 KB,我可以发送和接收 4 KB 的数据包。

我正在使用 android NDK (Linux) 进行开发。

请帮忙。我必须设置一个套接字选项来读取大缓冲区吗?

【问题讨论】:

    标签: linux sockets


    【解决方案1】:

    如果您发送的数据包大于 MTU,它将是 fragmented。也就是说,它将被分解成更小的部分,每个部分都适合 MTU。这样做的问题是,即使其中一个片段丢失(很可能在蜂窝连接上......),整个数据包也会有效地消失。

    要确定是否属于这种情况,您需要在连接的一端(或两端)使用数据包嗅探器。 Wireshark 是 PC 端的不错选择,或者是 android 端的 tcpdump(你需要 root)。请记住,家庭路由器可能会重新组装碎片数据包 - 这意味着如果您正在从家庭路由器/防火墙内部嗅探数据包,您可能不会看到任何碎片到达,直到它们全部到达路由器(显然,如果有些碎片正在获取失去这不会发生)。

    当然,更好的选择是确保您始终发送小于 MTU 的数据包。碎片化几乎从来都不是正确的做法。请记住,MTU 可能在服务器和客户端之间的路径上的不同跃点处有所不同 - 您可以使用小于 1500 的常用选择(1400 应该是安全的),或者尝试通过setting the MTU discovery flag on your UDP packets 进行探测(通过IP_MTU_DISCOVER)并始终发送小于getsockoptIP_MTU 选项返回的值(包括重传!)

    【讨论】:

    • 感谢您的回复。我会检查套接字选项
    • MTU 发现确实是一个不错的功能。遗憾的是,您只能为IP_MTU 执行getsockopt() 而不是setsockopt()。如果能够为 MTU 发现算法设置一个初始值,或者在使用自动 UPD/IP 数据包分段时设置一些首选的分段大小,那就太好了。或者一路走黑客风格,同时使用 MTU 发现和分段数据包。
    猜你喜欢
    • 1970-01-01
    • 2021-10-04
    • 1970-01-01
    • 1970-01-01
    • 2012-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多