【发布时间】:2012-07-06 13:51:41
【问题描述】:
我正在调用有效地址的 recvfrom api,我试图读取大小为 9600 字节的数据,我提供的缓冲区大小为 12KB,我什至没有收到选择读取事件。 甚至强硬推荐的 MTU 大小是 1.5 KB,我可以发送和接收 4 KB 的数据包。
我正在使用 android NDK (Linux) 进行开发。
请帮忙。我必须设置一个套接字选项来读取大缓冲区吗?
【问题讨论】:
我正在调用有效地址的 recvfrom api,我试图读取大小为 9600 字节的数据,我提供的缓冲区大小为 12KB,我什至没有收到选择读取事件。 甚至强硬推荐的 MTU 大小是 1.5 KB,我可以发送和接收 4 KB 的数据包。
我正在使用 android NDK (Linux) 进行开发。
请帮忙。我必须设置一个套接字选项来读取大缓冲区吗?
【问题讨论】:
如果您发送的数据包大于 MTU,它将是 fragmented。也就是说,它将被分解成更小的部分,每个部分都适合 MTU。这样做的问题是,即使其中一个片段丢失(很可能在蜂窝连接上......),整个数据包也会有效地消失。
要确定是否属于这种情况,您需要在连接的一端(或两端)使用数据包嗅探器。 Wireshark 是 PC 端的不错选择,或者是 android 端的 tcpdump(你需要 root)。请记住,家庭路由器可能会重新组装碎片数据包 - 这意味着如果您正在从家庭路由器/防火墙内部嗅探数据包,您可能不会看到任何碎片到达,直到它们全部到达路由器(显然,如果有些碎片正在获取失去这不会发生)。
当然,更好的选择是确保您始终发送小于 MTU 的数据包。碎片化几乎从来都不是正确的做法。请记住,MTU 可能在服务器和客户端之间的路径上的不同跃点处有所不同 - 您可以使用小于 1500 的常用选择(1400 应该是安全的),或者尝试通过setting the MTU discovery flag on your UDP packets 进行探测(通过IP_MTU_DISCOVER)并始终发送小于getsockopt 的IP_MTU 选项返回的值(包括重传!)
【讨论】:
IP_MTU 执行getsockopt() 而不是setsockopt()。如果能够为 MTU 发现算法设置一个初始值,或者在使用自动 UPD/IP 数据包分段时设置一些首选的分段大小,那就太好了。或者一路走黑客风格,同时使用 MTU 发现和分段数据包。