昨天同事给我看了一个有趣的 case,接收端抓包:

现象就是这样,但结论也很明显:

  • ack 渐长,win 渐缩,有数据陆续到达 rcvbuff,但 app 尚未读取。
  • ack 不变,win 渐长,没有新数据到达,app 持续读取数据。

据说这是个 iOS 系统的 case。

该现象与 Linux TCP 并不匹配,Linux TCP 仅在下面的情况才会发送 win update:

  • 窗口从 0 变为非 0,且…
  • rwnd 腾出了一半的空间。

条件过于苛刻。做以下实验:

Linux server 端代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>#define SIZE 16384
#define PORT 1234void senddata(int csd)
{char buff[SIZE];int n, i;for (i = 0; i < 8; i++) {write(csd, buff, sizeof(buff));}getchar();
}int main()
{int sockfd, csd, len;struct sockaddr_in servaddr, cli;sockfd = socket(AF_INET, SOCK_STREAM, 0);servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(PORT);bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));listen(sockfd, 5);len = sizeof(cli);while(1) {csd = accept(sockfd, (struct sockaddr *)&cli, &len);senddata(csd);close(csd);}
}

Linux client 和 MacOS client 端代码:

#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>#define SIZE 2048
#define PORT 1234void recvdata(int sd)
{char buff[SIZE];int n, i;getchar();for (i = 0; i < 64; i++) {read(sd, buff, sizeof(buff));}
}int main()
{int sd, connfd;struct sockaddr_in servaddr, cli;sd = socket(AF_INET, SOCK_STREAM, 0);servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = inet_addr("192.168.10.6");servaddr.sin_port = htons(PORT);connect(sd, (struct sockaddr*)&servaddr, sizeof(servaddr));recvdata(sd);close(sd);
}

运行 client 后敲回车,结果显示,MacOS client 在敲下会车后从 rcvbuff 读取了一定字节后就会发送 win update,而 Linux 不会。

OK,开始评谈。

早期,资源所限,为避免糊涂窗口综合症,TCP 采取一定措施规避,但在事情的反面反而阻碍了 rate-based 流控。

糊涂窗口综合症本质上包括下面因素:

  • 接收端接收数据太慢。
  • 发送端产生数据太慢。
  • 担心网络上充斥小包。

但根据管道模型,理论上哪怕一次通告 1 字节 rwnd,只要通告速度足够快,依然可达任意带宽。问题是:

  • 如果接收端接收速度足够快,窗口还糊涂吗?
  • 既然接收端慢可以影响发送,为什么接收端快就不能呢?

如何从面向 rcvbuff 的流控转向面向应用程序接收能力的 rate-based 流控,问题就在于何时发送 win update。Linux TCP 在应用程序读取数据后发送 win update 的条件太苛刻。

如今早年的限制已不再:

  • 内存足够大,可承受更大的意外突发。
  • 带宽足够大,可容忍长报头损失的载荷率。
  • 拥塞控制纷纷从 buffer-based 转向 rate-based。

Linux TCP 在 30 年后依然是很吝啬的实现,旨在节省资源以适应早期环境,MacOS 似乎好一点,但我还没 deep into Darwin 代码,不评说。

糊涂窗口综合症是慢速环境下的症状,减缓症状的措施在高速环境下必然掣肘。

看看 win update after read 的益处:

皮鞋不会胖
蜷缩着过活,总希望是大梦一场,
可我挺直了身子,却还是看不到光,
你说我不够努力,我说我没有梦想,
街头徘徊着梦,需要与酒邂逅。
浙江温州皮鞋湿,下雨进水不会胖。

TCP 糊涂窗口综合症(silly window syndrome)与 rate-based 流控相关推荐

  1. 糊涂窗口综合症和Nagle算法

    本篇文章转载自:http://www.cnblogs.com/zhaoyl/archive/2012/09/20/2695799.html,用于记录自己对于TCP网络中糊涂窗口综合症和Nagle算法的 ...

  2. TCP滑动窗口(Sliding Window)原理

    ---------------- 版权声明:本文为CSDN博主「CQ小子」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog.csd ...

  3. 传输层协议TCP—滑动窗口(6)

    1 传输控制 TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议.在前面的章节中,我们介绍了 TCP 连接的相关概念 ...

  4. TCP滑动窗口,流量控制,拥塞控制详解

    引言 我们知道TCP是每发送一个数据,都要进行一次确认应答报文的.当上一个收到应答时,才会继续发送下一个.这种方式很显然效率比较低 滑动窗口 窗口大小就是无需等待应答,而可以继续发送数据的最大值 滑动 ...

  5. tcp下载窗口太小的问题_图解 TCP 重传、滑动窗口、流量控制、拥塞控制

    相信大家都知道 TCP 是一个可靠传输的协议,那如何它是如何保证可靠的呢? 为了实现可靠性传输,需要考虑很多事情,例如数据的破坏.丢包.重复以及分片顺序混乱等问题.如不能解决这些问题,也就无从谈起可靠 ...

  6. tcp欢动窗口机制_TCP协议中的窗口机制------滑动窗口详解

    一.窗口机制的分类 在TCP协议当中窗口机制分为两种: 1.固定的窗口大小 2.滑动窗口 二.固定窗口存在的问题 如下图所示: 我们假设这个固定窗口的大小为1,也就是每次只能发送一个数据,只有接收方对 ...

  7. 互联网协议 — TCP — 滑动窗口

    目录 文章目录 目录 TCP ARQ 协议 TCP 的滑动窗口 Sender 滑动窗口 Receiver 滑动窗口 滑动窗口处理流程 窗口探测 TCP ARQ 协议 ARQ(Automatic Rep ...

  8. TCP三次握手、糊涂窗口、粘包问题

    这是在学习中的总结,若有错误请大家不吝指正(^.^) 关于TCP/IP的三次握手: 当服务端的状态为LISTEN,客户端的状态为CLOSED时,客户端发起连接 客户端发送有SYN字段报文,此时状态为S ...

  9. TCP接收窗口--确定Window

    1.  TCP接收窗口的调整 在上面配置的rcv_buf都是配置的接收缓存,在tcp层中接收窗口不能完全占满接收缓存,因为TCP层描述的接收窗口,仅仅是tcp层的data,不包含整个数据包的heade ...

最新文章

  1. 苹果设备iphone,ipad,macbook网络连接慢,开机开什么卡什么,一步解决
  2. 第 十 天 : 添 加 硬 盘 和 分 区 挂 载 等
  3. java基本数据类型自动转包装类,Java String和基本数据类型之间的转换(包装类)
  4. python xlwt xlrd 写入一行_Python Excel文件的读写操作(xlwt xlrd xlsxwriter)
  5. 【第二章】 IoC 之 2.1 IoC基础 ——跟我学Spring3
  6. 【理论】数据结构----树的基本概念
  7. PAT甲级1054 map的使用
  8. 周末休息整理B站项目过于敏感,2h后删!
  9. Nginx中保持长连接的配置 - 运维记录
  10. android studio 跳转后保留原页面数据_这些技巧和习惯,让你的原生 Android 手机更好用(上篇)...
  11. 证件照换底(红→蓝)
  12. 好心情:22个表达好心情的经典句子,送给抑郁焦虑的你
  13. 王逸凡的十万个为什么
  14. 视觉检测零件同轴度 测试零件同轴度,检测是否同心圆
  15. 解放前端工程师——手把手教你开发自己的自定义列表和自定义表单系列之一缘起
  16. iOS OC mvvm开发模式
  17. 10.Java面向对象进阶2
  18. suspend(挂起)和resume(继续执行)线程
  19. 记录若干`tf.py_function`的使用的方式,便于查阅
  20. 舆情监测系统对企业有什么作用,企业如何监测网络舆情危机?

热门文章

  1. Python基础复习--print()函数、转义符、变量命名
  2. Spring Boot 使用 Swagger3 生成 API 接口文档
  3. 首次使用Neptune3000海底静力触探CPT记录
  4. LayUI使用Echarts实现统计图
  5. Bio::DB::GenBank, Bio::SeqIO
  6. 《上海市居住证》积分申请基本流程
  7. vue进入浏览器大屏
  8. Libgdx slg游戏进程记录
  9. 如何引导回购和好评且不被平台抽查和处罚
  10. matlab和saber哪个好用,实例分析 saber与simulink谁更适合仿真