《TCP/IP详解》之二:流式数据交互

  和UDP这种“滚珠”式的协议不同(一份数据就是一个udp packet),TCP以报文段的方式传递数据,其大小受网络链路的限制。在SYN报文段中互相通告最大报文段长(MSS)。所以业务层交付的数据,会被TCP拆分/合并为合适的报文段(这也就是为嘛TCP数据跟水流似的,没有边界)。

  对于每个报文段而言,就很像UDP的“滚珠”了,不保证顺序、不保证到达。TCP要对收到的报文重新排序,再才交给应用层。发出一个报文段后,会启动一个定时器,等待对端ACK确认收到,否则将重传该报文。由于重传机制,报文段可能发生重复,接收端须丢弃重复报文。借此TCP实现了自己的可靠性。

  那如何高效实现此可靠系统呢?

  【ack确认】

  首先是ack的设计,最直白的方式:跟我们平时写异步IO很相似,发送一份数据,等待对方确认,再发下一份。

  由于TCP是双全工的,两端都可有数据交互,对端的ack可以合并至其正常报文段中,减少交互量。此即:“经受延时的确认”——通常TCP在接收到数据时并不立即发送ACK;相反,它推迟发送,以便将ACK与需要沿该方向发送的数据一起发送。

  再者,ACK是确认收到的字节序,未必每一条报文都须ACK,可一次ACK多条数据。比如连续收到两个报文段“PSH 1:1025; PSH 1025:2049”,只需回复一条“ack 2049”即可。此即:“隔一个报文段确认”策略——接收方不必确认每一个收到的分组,ACK是累积的,它们表示收方已正确收到了一直到确认序号减一的所有字节。

  【Nagle算法和滑动窗口】

  其次,我们是有宽带的,要是用户让发多少就发多少,会很浪费。好像200人的航班带两个人飞过。解决方案也很简单:

  一、限制小包的数目(Nagle算法,连接上最多只能有一个未确认的小分组,该分组的ack到达之前不能发送其他小分组了,算法是自适应的,收到的ack越快发的就越快);

  二、上buffer,缓存用户数据,再分发成块交给IP层传输,相应的对端也要要个接收buffer,两片buffer配合工作,保证收发正确性。

  这就是TCP最大特征的“滑动窗口”了。

  每条报文段的TCP头部中都会通告当前窗口大小,发送端据此得知可预留多少字节的buffer给应用层。具体工作流程如下图(请忽略字体,多谢):

  通告窗口为0,显示接收方虽已收到所有数据,但其应用层尚未及时从TcpRecvBuff中读取,发方会停止发送。

  Zero Window下,应用层读取数据后,窗口重新空闲,要通知发送方(窗口更新)。一个单独的主动ack,不确认数据,仅报告新的窗口大小。

  

  【坚持定时器】

  “单独的主动ack”,跟一般的ack不一样,还记得一般得ack丢了怎么重传的吗?那这货丢了怎么办?

  TCP四大定时器(重传、坚持、保活、2MSL)之坚持定时来搞定。

  Zero Window后,发方停止发送数据,并设置其坚持定时器,若超时前仍未收到窗口更新,则发送一个特殊的探查报文,获知对端窗口大小。探查含1字节,但不被ack确认,会一直重复。

  【糊涂窗口综合征】

  好,我们有了Nagle算法,有了滑动窗口,是不是就完全搞定了宽带高效利用呢?

  考虑这样一种场景,Zero Window后,收方应用程序每次仅拷走1个字节,触发窗口更新,ack win 1,发方窗口右边沿更新,发送了1字节数据,停止,等下一波窗口更新……loop(PS:实际不可能只是1字节,tcp头都20字节咧)

  相应的解决方案:

    1)接收方不通告小窗口,除非窗口增加至MSS(最大报文段长),或增加到接收方缓冲空间的一半。

    2)发送方只在下列条件之一满足时才发数据:

      (a) 可以发送一个满长度的报文段

      (b) 可以发送至少接收方窗口大小一半的报文段

      (c) 无未被确认的数据,且能够发送所有缓冲数据

      (d) 连接关闭了Nagle算法

  

  【拥塞避免、慢启动】

  还有问题吗?之前由于宽带利用问题,我们要滑动窗口,避免频繁发小包;类似的,由于路由问题,我们还得避免不要太粗暴。

  假设连接建立起始(窗口均空闲)便发送大量数据,塞满网络,而链路速率较慢——中间路由器就必须缓存分组了,一旦路由存储空间耗尽,后来的分组会被直接丢弃,TCP吞吐量便随之严重降低了。

  “慢启动、拥塞避免”上场——拥塞窗口(congestion window,记作cwnd),慢启动门限(ssthresh)。

  

  TCP连接建立时,ssthresh初始化为65535字节,拥塞窗口初始化为1个报文段(MSS),每收到一个ack,cwnd便增加一个报文段大小。发送方取min(拥塞窗口,滑动窗口)作为发送上限。

  发方先发送一个报文段,等ack,收到后cwnd增加到2,可发两个报文段。收到这两个报文段的ack时,cwnd增加到4……指数增涨(慢启动)。

  攀升到一定值后抵达网络容量,中间路由丢弃分组,发方重传定时器超时,知晓cwnd过大引起拥塞,cwnd被重设为1个报文段,ssthresh则被设置为当前cwnd的一半。

  还有种拥塞指示:收到重复ack,比如中间某报文损坏。此时仅设置ssthresh = cwnd/2,并不改写cwnd。

  若 cwnd <= ssthresh,则进行慢启动,cwnd按指数更新;否则进行拥塞避免,cwnd按线性方式增长(每次ack增加1/cwnd,一个RTT内最多增加一个报文段,无论期间受到多少个ack)。

时间: 2024-08-08 22:04:37

《TCP/IP详解》之二:流式数据交互的相关文章

TCP/IP详解(二)

首先,不得不吐槽一下中文版的翻译,把英文版的很多部分的删除了.中文版的pdf只有400多页,英文版有1000多页.迫于时间,只有先将就着看中文版,但是遇到不懂的地方,一定要对照英文版来看. 滑动窗口协议 对于TCP的任何一端,都可以接受和发送数据,因此任何一端都维护着两个窗口,发送窗口和接收窗口. 发送窗口: 发送窗口的大小是对端回发的TCP报文首部里的通告窗口大小(offered window). 发送窗口的左边(Left Edge以左)是对端已经确认过的bytes(注意不是packets),

TCP/IP详解 学习二

链路层: 在 T C P / I P协议族中,链路层主要有三个目的:(1)为 I P模块发送和接收 I P数据报:( 2)为 A R P模块发送 A R P请求和接收 A R P应答:( 3)为 R A R P发送 R A R P请求和接收 R A R P应答. 以太网和IEEE 802封装: 以太网:般是指数字设备公司( Digital Equipment Corp.).英特尔公司( I n t e lC o r p .)和 X e r o x公司在 1 9 8 2年联合公布的一个标准.它是当

【转】TCP/IP详解学习笔记(二)

TCP/IP详解学习笔记(5)-IP选路,动态选路,和一些细节 1.静态IP选路 1.1.一个简单的路由表 选路是IP层最重要的一个功能之一.前面的部分已经简单的讲过路由器是通过何种规则来根据IP数据包的IP地址来选择路由.这里就不重复了.首先来看看一个简单的系统路由表. Destination     Gateway         Genmask         Flags Metric Ref    Use Iface192.168.11.0    *               255.

转:TCP/IP详解--举例明白发送/接收缓冲区、滑动窗口协议之间的关系

原文地址:http://blog.csdn.net/yusiguyuan/article/details/21439633#1536434-tsina-1-74921-66a1f5d8f89e9ad52626f6f40fdeadaa  TCP/IP详解--举例明白发送/接收缓冲区.滑动窗口协议之间的关系. 一个例子明白发送缓冲区.接受缓冲区.滑动窗口协议之间的关系. 在上面的几篇文章中简单介绍了上述几个概念在TCP网络编程中的关系,也对应了几个基本socket系统调用的几个行为,这里再列举一个例

《TCP/IP详解卷1:协议》第14章 DNS:域名系统---读书笔记

<TCP/IP详解卷1:协议>第14章 DNS:域名系统---读书笔记 1.引言 5.指针查询 DNS中一直难于理解的部分就是指针查询方式,即给定一个IP地址,返回与该地址对应的域名. 当一个组织加入Internet,并获得DNS域名空间的授权,如noao.edu,则它们也获得了对应IP地址的in-addr.arpa域名空间的授权.在noao.edu这个例子中,它的网络号是140.252的B类网络.在DNS树中结点in-addr.arpa的下一级必须是该IP地址的第一字节(例中为140),再下

TCP/IP详解之一:连接建立、断开

<TCP/IP详解·卷一>看了三遍才算整明白个大概,一直想做个总结. 最初对TCP的印象很简单:丢包重传.流数据.丢包重传很好理解,“流数据”是什么鬼? 知乎上看到个极好的解释:把TCP看作用管子往对端灌水,水是数据,它们之间没有边界,且先发先到:UDP是往对端滚小球,它们之间有明确边界,且可能每个小球速度不同,先滚的不一定先到,得自己处理乱序. 编码上也可看出,TCP的send回调带有dwNumberOfBytesTransferred参数,描述本次网络IO发送了多少字节数据,而不是给它多少

《TCP/IP详解卷2:实现》笔记--IP选项处理

IP输入函数(ipintr)将在验证分组格式(检验和,长度等)之后,确定分组是否到达目的地之前,对选项进行处理.这表明分组所 遇到的每个路由器以及最终的目的主机都对要分组的选项进行处理. IP分组内可以包含某些在分组被转发或被接收之前处理的可选字段.IP实现可以用任意顺序处理选项.标准IP首部之后最多可跟 40字节的选项. 1.选项格式 IP选项字段可能包含0个或多个单独选项.选项有两种类型,单字节和多字节.如图所示: 所有选项都以1字节类型type字段开始.在多字节选项中,类型字段后面紧接着一

有了Openvswitch和Docker,终于可以做《TCP/IP详解》的实验了!

所有做过网络编程的程序员,想必都会看<TCP/IP详解>卷一:协议 后来出了第二版,但是由于第一版才是Rechard Stevens的原版,本人还是多次看了第一版. 对这一版印象最深的就是下面这个拓扑图 书上的很多实验,都是基于这个图做的,看了实验结果,很多理论才有真实的感觉. 看这本书的时候,不尽感慨Rechard Stevens的天赋英才,他能够利用工作中当时少于的实验环境,做了大量的实验,写出了普惠程序员的这本书. 可是除了看书中的实验结果,如何能够模拟这么一个环境,也动手测试一下呢?

《TCP/IP详解》

[TCP的那些事儿]TCP是个巨复杂的协议,而且不断地改进中.所以学习TCP本身是个比较痛苦的过程,但这个过程却能让人有很多收获.希望这篇快餐科普性文章能在快餐文化下让你对TCP有了解,并可以促发你对基础知识的兴趣和学习欲望. http://coolshell.cn/articles/11564.html http://coolshell.cn/articles/11609.html 大家知道,TCP/IP已成为计算机网络的事实上的标准.在关于TCP/IP的论著中,最有影响的就是两部著作.一部是

《TCP/IP详解卷1:协议》第17、18章 TCP:传输控制协议(2)-读书笔记

章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP:网际协议(1)-读书笔记 <TCP/IP详解卷1:协议>第3章 IP:网际协议(2)-读书笔记 <TCP/IP详解卷1:协议>第4章 ARP:地址解析协议-读书笔记 <TCP/IP详解卷1:协议>第5章 RARP:逆地址解析协议-读书笔记 <TCP/IP详解卷1:协