我正在编写一些服务器软件来升级电子设备上的固件。这是一项棘手的任务,因为目前这些设备在安装之前没有足够的内存来保存完整的固件。结果,我的服务器会将设备切换到引导加载程序模式,并指示引导加载程序做什么,通过网络发送指令和固件数据。可以想象,这有一些潜在的巨大缺点。
我现在关心的是,我发送的单个 TCP 段是否会被分成多个以太网帧?
由于引导加载程序的性质,我可以在 TCP 段中发送的最大有效负载为 255 字节。
从 Wireshark 中抓取数据包来看,包含我的 TCP 段之一的帧的帧大小似乎是 309 字节(2,472 位),完全在以太网帧上的维基百科页面允许的范围内:
我目前正在尝试处理如果与设备的连接被切断会发生什么。就像现在一样,我可以毫无困难地重新建立与设备的连接,但我想确定的是重新建立连接后会发生什么。
如果我可以确定每条指令将始终包含在单个以太网帧中,并且因此,要么交付要么不交付,那么快乐的日子!我可以查看发送的最后一条指令并弄清楚接下来要做什么。
但是,如果有可能将指令拆分为两个以太网帧,那么我的问题就更大了。我认为它不应该发生,但有时在我测试时看起来会发生这种情况。
假设我已经发出了一个写命令,并且引导加载程序正在等待数据写入,我发送了 255 字节的 TCP 段,它被分成两个以太网帧。第一帧被传递,但第二帧没有。现在,当我重新连接时,我必须弄清楚引导加载程序已经收到了多少字节,这意味着我需要推送虚拟数据并监听响应。如果可能的话,我真的很想避免这种情况。
从这个线程中的评论来看,小于 576 字节(4,608 位)的 IP 数据包似乎不会被拆分。我可以安全地假设情况总是如此吗?
实际上,如果它被拆分,那么 WiFi 模块不应该在重新组装之前交付 TCP 段,不是吗?如果连接丢失,它将被丢弃。
一般来说,很难控制数据包是否被拆分。实际上,您需要深入了解堆栈 - 诸如将 TCP 卸载到硬件之类的事情也可能会妨碍并创建针对传输进行优化的数据包。
但是你说的是 TCP 连接——所以如果你的连接有一个短暂的中断,应该不会有任何问题。如果单个 TCP 数据包被拆分为多个以太网数据包,并且您的连接在单个帧的传输之间断开(短时间内),则 TCP 将重试传输数据包(这是协议的一部分)。
有一个更长的/检测到的断开连接,一个更大的问题将是事实,你不能在不重新建立新连接的情况下继续发送(这需要你的设备支持) - 设置一个新的套接字并发送到同一个任何默认堆栈都可能不支持没有 TCP syn/ack 的远程主机。
关于您想要的目标(如果可能),我建议在固件升级期间采用适当的方法来处理中断(例如双启动)。
如果这是不可能的并且您没有实现自己的 TCP/IP 堆栈,我只能建议禁用服务器上的任何硬件加速(以防止硬件重新组装数据包)并在套接字连接上禁用nagle 算法。