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