不可靠不重传的 tcp 新魔改

原文参见 不可靠的假 tcp

最近在研究可纠错的编码,新想法就比上述引文成熟了很多。新的魔改更加合理:

  • 当 receiver 收到报文时,根据一个变量 k 来确定回复哪个序列号作为 ack。

应用层可以简单定时设置 k,让 k 匀速往后滑动,就能实现一个固定时延的传输,在 buffer 允许的范围,tcp 重传依然有效,只是过了 buffer 允许的时间,receiver 补洞上送,不再需要重传,强行设置 k,推进 sender 的 una。

可调节的 buffer 为丢包纠错提供了操作时间。

代码的修改并不麻烦,重写少部分 tcp_data_queue 即可。

之所以要这么做而不是设计一个新的协议,原因是设计一个新协议几乎总是会引入更多的问题,一破一立的思路对于网络传输协议并不总合适,因此我也非常讨厌近些年那些层出不穷的新协议总是由揭露现有协议不适合某些场景开始,以一个针对特殊场景的全新协议结束,一篇又一篇地水论文。

我倾向于迭代现有协议。首先为现有协议增加可扩展性支持,然后在此基础上扩展现有协议。

对上述修改而言,如果真有确实不能丢的数据,我将引入一条单独的 nack 通道,或 http over tcp/quic,或 rpc 不重要,用 receiver 主动索要丢失的数据的方式代替 sender 重传才是重点,哪些数据必须要,只有 receiver 最清楚(比如说即使采用了纠错机制依然没有恢复成功)。

该修改的另一优势是为完全的乱序传输增加了灵活性。我一向倾向于 “用素描的方式画油画”,而不是 “一笔画”,根据 receiver 的 qoe 容忍度来决定这幅画的颜料涂到多厚,而不是稍有断笔就擦去重改,任何 sack-based 重传机制都内含了 gbn 的影子。

以传输一幅画为例,画面像素要均匀打在屏幕上,一次一点点,越来越清晰,根据资源情况和 qoe 容忍度随时停止,这才是合理方式,就像素描和油画一样,现实世界我们也如此,而只有乱序传输才能支持。

说了这么多好处,当我测试时才发现,天啊,拥塞控制完全失效了。

我使用了系统自带的 bbrv1,结果 bbr 相关的计算完全失真。原因不难查,由于 receiver 主动推进了 una,大量丢包便没被计入,从而严重影响了 sender 的 delivery rate 计算。

解决这个问题的思路天然地倾斜到 “在那个单独的通道中回传 sack 以及丢包统计信息”,这些信息通过单独通道给到 sender 用于拥塞控制。你看,这个单独的通道是不是自然而然变成了 “控制通道”,拥塞控制就是这样从 tcp 带内自然剥离出来的。

为什么包括我自己在内的几乎所有人都没有剥离控制通道的想法,因为 tcp 从最开始就是带内控制协议,自然就成了缺省标准,这就是思维定势,然而谁告诉我们传输协议就一定要带内控制。

单独的控制通道还没有改完,不过既然控制信息都拉到应用层了,格式都是我自己定,也就没必要迎合哪个协议了,简单。

再次强调,控制信息拉到应用层很重要,只有 receiver 应用层自己知道自己收到没收到哪些数据,单位时间收到多少数据,以及还需要哪些数据。控制通道解耦后更自由,测不准问题也得到了解决。

所以,最终 tcp 几乎还是原来的 tcp,如果不设置 k,就是兼容模式,而设置了 k,单独的控制通道也不影响原始 tcp。

我这个就是 tcp 本身,不是新协议,一个 k 值可用可不用,这对于平滑落地非常重要。

前些天给孩子们讲完课写了一篇 开始干重活儿的互联网,有朋友跟我一个想法,认为 “Xpu 确实是各种很难想到的特定使用场景”,非常类似我最近提到的作为自我检讨用的 “自动切豆腐篦子”,我也就再评论几句 “就跟肥皂剧泛滥一样,你水一篇论文,虚构一个场景,我也必须水一篇论文,虚构一个场景,然后我拿着你的论文说你这个场景不适合我的场景,把你的论文稍微加点东西变成我的,你也觉得我的论文不适合你的场景,稍微改改变成你的,各种虚构+虚构场景,各种魔改版本”。

曾经我不懂,但现在懂了,工程上弹性和余量非常重要,千万不要开足马力奔赴一个特定的目的。举两个例子,一个是服务器负载均衡,一个是 4 发动机大型客机。

集群中的服务器在 cpu 利用率超过 50% 时就要警惕集群中一半服务器的宕机,如果 cpu 利用率超过 90%,哪怕几台服务器宕机,压力也会很快传播到整个集群,连锁反应将干崩整个集群。早期的我经常认为 active-active 远胜 active-standby,我甚至希望把 active 开到接近 100%,因为我只想着性能。

同样,大型客机的 4 个发动机也并不是用于性能,而是用于在某发动机失效后,接管发动机可迫降,而用于跨洋超远距离运输的客机,必须有足够的余量支撑这个原则。

我们现在的传输协议设计几乎忽略了这些弹性和余量的原则,几乎都是开足马力奔赴特定目的,大家普遍都希望自己的协议可以 n for one,但事实上只是由 n 变成了 n + 1。但只要松弛一下这种紧张的局面就能缓解,我用带外信号做控制,而带外意味着无限扩展的弹性和余量。

后记:

  • 我本想用 ebpf 做自定义 ack,太麻烦了,放弃,从此不碰 ebpf。
  • 切豆腐篦子真不需要,不是刚需。新传输协议哪个又是刚需?能改造一下,何必重做一个?

浙江温州皮鞋湿,下雨进水不会胖。

  • 23
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 使用 LabVIEW 进行 TCP 通信时,有时会出现通信断开的情况。一旦通信断开,重连接服务器或客户端很重要。 然而,有时重连接会失败,导致无法建立TCP 连接。这可能是由于连接未完全关闭或操作系统资源不足导致的连接限制造成的。要解决这个问题,需要采取以下几种措施: 1. 强制关闭TCP连接: 如果出现通信问题,需要确保及时关闭所有的 TCP 连接。请使用 TCP Close 相关的VIs 来关闭 TCP 连接。确保调用此 VI 之后,所有的资源被释放,并可以再次使用。 2. 增加自动重连功能: 通过添加自动重连功能,即使服务器或客户端暂时断开连接,LabVIEW 也能够在连接恢复时自动重连接。在确定连接状态时,可以将 Timeout Input 设置得更高以防止连接超时。 3. 优化系统资源: 可能存在系统资源紧缺的情况,这可能成为无法重连接的主要因素。在这种情况下,需要分析计算机硬件和操作系统状态,并可能采取一些措施来优化操作系统以获取更多的资源。 总之,LabVIEW TCP 通信断开不能重连的问题可能是由多种原因造成的,可以根据上述措施来解决此问题。 ### 回答2: 在LabVIEW中,使用TCP/IP协议进行通讯时,经常会遇到通讯断开后不能重连的问题。这是由于TCP/IP协议本身的特性所导致的,因此我们需要在LabVIEW程序设计过程中注意以下几点: 首先,需要确保在TCP通讯初始化之后,设置超时选项,以确保及时检测连接状况。如果超时时间设置得过长,可能会导致程序无法及时响应连接中断或异常,从而造成不能重连的情况。 其次,在程序设计过程中,需要考虑网络环境的复杂性和不稳定性。如果网络不稳定或者通讯质量较差,可能会导致数据包丢失或通讯中断,从而无法建立的连接。针对这种情况,我们可以采用心跳包技术,定期发送数据包来检测连接状态,并在检测到连接中断时进行重连接。 此外,还需要注意程序中的资源释放和错误处理机制。如果程序中没有正确释放相关的资源或处理异常情况,可能会导致程序无法重进行连接,需要通过手动清理的方式才能重连接。 总之,要实现TCP通讯的断开重连功能,在设计程序时需要考虑网络环境、超时设置、心跳包机制和资源释放等多个方面,才能确保程序的稳定性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值