和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是累积的,它们表示收方已正确收到了一直到确认序号减一的所有字节。

  【快速重传】

  如果数据丢失/错误,每次都等超时才重传会慢。

  收到一个失序报文段(前面一条丢失/错误/暂未抵达),TCP立即产生一个ack(重复的,且不被延时),如果发方连续收到3(或以上)次相同的ack,就非常可能是报文段丢失/错误,于是重传报文段,不必等timeout。

  (PS:为什么是3次,查资料说是经验数据,连续3次,即表示嫌疑报文后的两条报文都正在到达对端了,由于由于链路层的失序造成的时差几乎不可能如此剧烈,可以认为是丢了或校验出错)

  还有重传哪些报文段的问题。譬如连续发生5条报文,第二条丢了,其它均到达,发方收到4个ack(2),仅知道2号报文必须重传,3/4/5号是不清楚的(某些TCP实现采用的是重传丢包后的所有报文)。

  可在TCP包头中加入SACK,汇报收到的数据碎片,这样发送端就可知道哪些数据到了,哪些是丢了。还是刚才的例子,发方仍收到4个ack(2),多了sack:sack(1, 3-5)。

  【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)。

转载于:https://www.cnblogs.com/3workman/p/5738328.html

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

  1. cdt规约报文用程序解析_程序员必备的学习笔记《TCP/IP详解(二)》

    把这三个协议放到一起学习是因为这三个协议处于同一层,ARP 协议用来找到目标主机的 Ethernet 网卡 Mac 地址,IP 则承载要发 送的消息.数据链路层可以从 ARP 得到数据的传送信息,而从 ...

  2. TCP/IP详解 第十二章(10) TCP Socket 编程

    前言 不管面试 Java .C/C++.Python 等开发岗位, TCP 的知识点可以说是的必问的了. 任 TCP 虐我千百遍,我仍待 TCP 如初恋. 遥想小林当年校招时常因 TCP 面试题被刷, ...

  3. TCP/IP详解 第十二章(9) TCP断开连接

    前言 不管面试 Java .C/C++.Python 等开发岗位, TCP 的知识点可以说是的必问的了. 任 TCP 虐我千百遍,我仍待 TCP 如初恋. 遥想小林当年校招时常因 TCP 面试题被刷, ...

  4. 《TCP/IP详解·卷1:协议》随笔(已完结)

    第一章.概述 Internet的成功 Internet体系结构被设计成支持现有网络互联,同时提供了广泛的服务与协议操作. 选用数据包的分组交换主要是因为它的鲁棒性与效率,而相对来说数据安全性与交付可预 ...

  5. 《TCP/IP详解》卷一:The-internet-protocol-IP

    引言 ​ IP是TCP/IP协议簇中最核心的协议之一.IP提供不可靠.无连接的数据报传输服务. ​ 不可靠(unreliable)的意思是IP不能保证数据报能成功地到达目的地,它仅仅尽最大努力提供最好 ...

  6. TCP/IP详解--第一章

    说明:专栏中的内容是<TCP/IP详解>这本书,博主分享在此. 第1章概     述 1.1   引言 很多不同的厂家生产各种型号的计算机,它们运行完全不同的操作系统,但  TCP/IP协 ...

  7. 《TCP/IP详解 卷1:协议》第4章 ARP:地址解析协议

    4.1 引言 本章我们要讨论的问题是只对TCP/IP协议簇有意义的IP地址.数据链路如以太网或令牌环网都有自己的寻址机制(常常为48 bit地址),这是使用数据链路的任何网络层都必须遵从的.一个网络如 ...

  8. 《TCP/IP详解卷1:协议》读书笔记

    <TCP/IP详解卷1:协议>读书笔记 - QingLiXueShi - 博客园 https://www.cnblogs.com/mengwang024/p/4425834.html &l ...

  9. 《TCP/IP详解卷1》学习小结(一)------链接层

    开始学习<TCP/IP详解卷1>这本著作,每一章都要写一篇学习小结.        一.  总述 链接层位于整个网络协议suite的最低一层,与硬件关系密切,比如以太网,token rin ...

  10. TCP/IP详解卷一读书笔记一

    TCP/IP详解卷一:第一章 一.分层   1.网络协议通常分不同层次进行开发,每一层分别负责不同的通信功能.   疑点 介质访问控制方法   多个主机需要通过一条"共享介质"发送 ...

最新文章

  1. MySql错误代码1045的解决方案(修改密码)
  2. 使用opencv自带的融合函数
  3. 后台运行定位,音频,网络电话
  4. java getSource()和 getActionCommand()
  5. mysql online ddl 5.6_MySQL 5.6的Online DDL功能测试
  6. Guice之Servlet基础
  7. 《构建之法》1、2、3章读后感
  8. Hibernate【2】——封装工具、HibernateUtil类以及DAO层的BaseDAO类
  9. linux无线adb,linux 无法连接adb 设备
  10. Visual Assist X 10.9 builds 2333 with patch.7z
  11. CANoe操作介绍系列 ———— Analysi功能区中Graphic的介绍与使用
  12. 点击高德地图标注没法弹窗_巴彦淖尔果农注意啦!林草局喊你上高德地图标注位置哦...
  13. 线性代数-矩阵及其运算(总结)
  14. 活动目录功能级别降级
  15. java怎么把毫秒转换成天数_java – 如何将毫秒转换成小时和数天?
  16. PowerDesigner工具箱(palette)关了如何重新打开
  17. 微信小程序之百度地图之定位AND输入地址定位AND输入经纬度定位
  18. 炫彩流光按钮 CSS + HTML
  19. unity gameframework starforce学习1
  20. ubuntu8.04下 安装IE +讯雷

热门文章

  1. Linux下程序的保护机制(checksec)
  2. struts2.2.1关于sitemesh和freemarker整合的细节
  3. map构造同时初始化
  4. C#从excel中将数据导出到datatable
  5. Ubuntu上sublime配置nodejs运行环境
  6. linux系统定时任务crond入门
  7. 编写高质量代码:改善Java程序的151个建议(第1章:JAVA开发中通用的方法和准则___建议1~5)...
  8. 1029 C语言文法定义
  9. 在Silverlight+WCF中应用以角色为基础的安全模式(一)基础篇之角色为基础的安全模式简介...
  10. BeanUtils.copyProperties