第19章 TCP的交互数据流
所属:TCP/IP详解 卷1:协议 来源:TCP/IP详解 卷1:协议
本章介绍TCP的交互数据流,包括交互式输入、经受时延的确认、Nagle算法等。
19.1 引言
交互数据流
交互数据流(Interactive Data Flow):
- 交互式应用的数据
- 比如远程登录(Telnet, Rlogin)
- 每次发一点点数据
- 一个字符一个字符地发
- 小包很多
交互式应用产生很多小包。
交互数据流的特点
交互数据流的特点:
-
数据量小
- 每次一个字符或几个字符
- 小包很多
-
实时性要求高
- 输入要马上有反应
- 延迟要小
-
双向交互
- 客户端发输入
- 服务器回显
- 一来一回
-
小包问题
- 40字节首部 + 1字节数据
- 效率很低
- 网络负担重
交互式应用的特点是小包多。
本章讨论的内容
本章讨论的内容:
- 交互式输入
- 经受时延的确认
- Nagle算法
- 窗口大小通告
- 糊涂窗口综合征
本章介绍交互数据流的处理。
19.2 交互式输入
远程登录的例子
远程登录的例子:
- 用户敲一个键
- 客户端发一个字符给服务器
- 服务器收到,回显这个字符
- 客户端收到回显,显示给用户
数据流:
客户端 → 服务器:1字节数据(字符)
服务器 → 客户端:1字节数据(回显) + ACK
客户端 → 服务器:ACK
问题:
- 一个字符产生三个包
- 40字节首部 + 1字节数据
- 效率极低
- 网络负担重
一个字符产生很多包。
小包的问题
小包的问题:
-
效率低
- 首部开销大
- 40字节首部,1字节数据
- 利用率只有2.5%
-
网络负担重
- 包的数量多
- 路由器处理每个包
- 负担重
-
拥塞
- 太多小包
- 容易拥塞
小包效率很低。
19.3 经受时延的确认
什么是经受时延的确认
经受时延的确认(Delayed ACK):
- 收到数据不马上确认
- 等一会儿
- 看看有没有数据要发
- 有数据就捎带确认
- 没有就单独发确认
目的:
- 减少包的数量
- 用一个包既发数据又发确认
- 提高效率
延迟确认,等捎带。
时延的时间
时延的时间:
- 通常是200ms
- 最多等200ms
- 等不到数据就单独发ACK
- 不能等太久,不然影响RTT测量
为什么是200ms:
- 平衡效率和延迟
- 等太久影响性能
- 等太短没效果
最多等200ms。
什么时候不延迟
什么时候不延迟,马上发ACK:
-
收到乱序的段
- 要马上发ACK
- 告诉发送方缺了什么
- 让发送方快点重传
-
收到FIN
- 要马上ACK
- 不能等
-
缓冲区满了一半以上
- 要马上通告窗口
- 让发送方知道
有些情况要马上发ACK。
效果
延迟确认的效果:
- 减少ACK的数量
- 很多ACK被捎带了
- 减少网络流量
- 提高效率
代价:
- 确认稍微晚一点
- 但通常不影响
- 因为有数据捎带
延迟确认减少包数量。
19.4 Nagle算法
什么是Nagle算法
Nagle算法:
- 解决小包太多的问题
- 要求:
- 一个连接上最多只能有一个未被确认的小包
- 在收到ACK之前,不能发更多小包
- 收集小包,等ACK来了一起发
- 或者攒够一个大包再发
目的:
- 减少小包数量
- 提高网络利用率
- 防止拥塞
Nagle算法减少小包。
Nagle算法的规则
Nagle算法的规则:
-
如果窗口够大,数据够多
- 发一个最大段
- 正常发
-
如果有未确认的数据
- 把小数据放缓冲区
- 攒着
- 等ACK来了再发
- 或者攒够一个MSS再发
-
如果没有未确认的数据
- 有数据就马上发
- 不管大小
最多一个未确认的小包。
例子
例子:用户快速敲键盘
没有Nagle:
- 敲一个发一个
- 每个字符一个包
- 很多小包
有Nagle:
- 敲第一个字符,发出去
- 等ACK的时候,又敲了几个字符
- 攒起来
- ACK来了,把攒的一起发
- 包的数量大大减少
Nagle算法把小包攒起来发。
Nagle算法的优缺点
优点:
- 减少小包数量
- 提高网络利用率
- 防止拥塞
- 简单有效
缺点:
- 增加延迟
- 交互式应用可能感觉慢
- 比如游戏、实时应用
关闭Nagle:
- 可以用TCP_NODELAY选项关闭
- 需要低延迟的应用可以关
- 但要注意不要造成拥塞
Nagle算法有好有坏。
19.5 窗口大小通告
窗口更新
窗口更新(Window Update):
- 接收方应用读取了数据
- 缓冲区有空间了
- 发送窗口更新
- 告诉发送方窗口变大了
什么时候发窗口更新:
- 应用读取数据后
- 窗口增加了一定量
- 通告发送方
窗口更新通告窗口大小。
窗口通告的时机
窗口通告的时机:
- 有数据要发的时候,捎带
- 没有数据的时候,单独发
- 窗口变化大的时候发
- 小变化不发,减少包
为什么小变化不发:
- 免得窗口更新包太多
- 等变化大了再发
- 减少包数量
窗口大变化才通告。
19.6 糊涂窗口综合征
什么是糊涂窗口综合征
糊涂窗口综合征(Silly Window Syndrome, SWS):
- 接收方窗口很小了
- 发送方也发很小的包
- 窗口一点点增加
- 一点点发
- 全是小包
- 效率极低
为什么叫糊涂:
- 窗口小得可笑
- 发的数据还没有首部大
- 很糊涂
糊涂窗口综合征就是全是小包。
产生的原因
产生的原因:
-
接收方
- 应用一次读一点点
- 窗口一点点增加
- 每次增加就通告
- 发送方就发一点点
-
发送方
- 应用一次发一点点
- 发送方有数据就发
- 不管大小
- 全是小包
双方都可能导致。
解决方法
解决方法:
接收方的解决:
- 不要窗口增加一点就通告
- 等窗口增加到一定程度再通告
- 至少一个MSS
- 或者缓冲区的一半
- 避免小窗口
发送方的解决:
- 不要有一点数据就发
- 等数据够多了再发
- 至少一个MSS
- 或者等ACK
- Nagle算法就是干这个的
双方都要避免。
接收方的避免
接收方避免SWS:
- 窗口小的时候不通告
- 等窗口够大了再通告
- 至少一个MSS
- 或者缓冲区的一半
为什么:
- 免得发送方发小包
- 窗口大了,发送方才能发大包
- 效率才高
接收方等窗口够大了再通告。
发送方的避免
发送方避免SWS:
- Nagle算法
- 不要有一点数据就发
- 攒够了再发
- 或者等ACK
为什么:
- 减少小包
- 提高效率
- 防止拥塞
发送方用Nagle算法避免。
19.7 小结
交互数据流
-
特点
- 数据量小
- 小包多
- 实时性要求高
- 效率低
-
问题
- 首部开销大
- 网络负担重
- 容易拥塞
经受时延的确认
-
什么是延迟确认
- 收到数据不马上ACK
- 等一会儿
- 看看能不能捎带
-
时延时间
- 通常200ms
- 最多等200ms
-
什么时候不延迟
- 乱序段
- 收到FIN
- 窗口变化大
-
效果
- 减少ACK数量
- 提高效率
Nagle算法
-
什么是Nagle算法
- 解决小包太多
- 最多一个未确认的小包
- 攒小包一起发
-
规则
- 有未确认数据就攒着
- 等ACK或攒够MSS
- 没有就马上发
-
优缺点
- 优点:减少小包,提高效率
- 缺点:增加延迟
-
关闭
- TCP_NODELAY
- 需要低延迟的应用
窗口大小通告
-
窗口更新
- 应用读了数据
- 通告窗口变大
-
通告时机
- 捎带最好
- 变化大才单独发
- 减少包数量
糊涂窗口综合征
-
什么是SWS
- 窗口很小
- 全是小包
- 效率极低
-
原因
- 接收方:窗口一点点增加
- 发送方:数据一点点发
-
解决方法
- 接收方:等窗口够大再通告
- 发送方:Nagle算法,攒够再发
-
接收方避免
- 至少一个MSS
- 或缓冲区一半
-
发送方避免
- Nagle算法
- 攒够了再发
关键概念
-
交互数据流
- 小包多
- 效率低
-
延迟确认
- 等捎带
- 减少ACK
-
Nagle算法
- 减少小包
- 攒着发
-
糊涂窗口综合征
- 小窗口小包
- 双方都要避免