本文是《TCP-IP详解.卷1 协议》的读书笔记


1 TCP简介

TCP提供一种可靠的、面向连接的字节流服务。TCP通过下面的方式来保证服务是可靠的:

  • 应用程序被分隔成TCP认为最适合发送的数据块,数据报的长度将保持不变(也就是说每次传送的报文段的大小是一样的);
  • 当TCP发出一个报文段后,就会启动一个定时器,等待对方确认收到这个报文段,如果在这个时间内没有收到确认,则会重传这个报文段;
  • 当TCP收到另一端的数据后,会发送一个确认;
  • TCP保持首部和数据的检验和,这是端到端的检验和,如果收到数据的检验和有错,则不确认这个报文段(等待重传);T
  • CP报文段是封装为IP数据报来发送的,因此到达时可能会失序,因此TCP会提供重新排序的功能,将正确的数据交给应用层。
  • TCP会丢弃重复的报文段;
  • TCP还提供流量控制,连接的双方都有一个缓冲区,另一端只允许发送接收端缓冲区所能接受的大小的数据;

对于每个连接,TCP会维护四个不同的定时器:

  • 1)重传定时器:定义希望收到另一端的确认的最长时间;
  • 2)坚持定时器(persist):使窗口大小信息 保持不断流动;
  • 3)保活定时器:用来检测连接的另一端什么时候崩溃或重启了;
  • 4)2MSL定时器:用来测量一个连接处于TIME_WAIT状态的时间;

1.1TCP首部

TCP的数据会被封装在一个IP数据报中,如下图:

TCP的首部如下图:

2 TCP连接的建立与终止

2.1 TCP连接的建立

建立一条TCP连接过程如下:

1)请求端(客户端)发送一个SYN段,指明客户打算连接的服务器的端口号,以及初始序号(ISN,在这个例子中为:1415531521)。这个SYN段为报文段1;

2)服务器发回包含服务器初始序号的SYN报文段(报文段2)作为应答。同时将确认序号设置为客户的ISN加1以对客户的SYN进行确认。一个SYN占用一个序号;

3)客户端必须将确认序号设置为服务器的ISN加1对服务器的SYN报文段进行确认(报文段3);

这三条报文完成连接的建立,建立与终止的过程如下图:

报文段1,2,3完成TCP连接的建立,报文段4,5,6,7完成连接的终止过程(中间省略了一些数据传送的报文),接下来会介绍终止的具体过程。

2.2 TCP连接的终止

终止一个TCP连接需要4次握手,也就是4个报文段,这是由于TCP是全双工的(每个方向都可以传送数据)导致的,因此连接的每一端都需要单独地进行关闭;当一方完成数据发送后就可以发送一个FIN来告诉另一方自己的数据已经发完了,而另一方在收到FIN后仍然可以发送数据。连接终止的过程如下:

1)客户端发送一个FIN用来关闭从客户端到服务器的数据的传送(报文段4);

2)服务器在收到FIN后,发回一个ACK,确认序号为收到的序号加1(报文段5)。同时还会向客户端发送一个文件结束符FIN来关闭连接(报文段6);

3)客户端在收到服务器的FIN后,必须发回一个确认(确认序号为收到的序号加1)(报文段7);

当TCP处于连接或终止的不同状态时,状态也是不一样的,TCP的状态变迁图为:

2.3 2MSL等待状态

TIME_WAIT状态也叫2MSL等待状态,每个TCP的实现都必须选择一个报文段的最大生存时间MSL(Maximum Segment LifeTime),这是每个报文段在网络内存活的最长时间。对于给定的MSL值,当TCP执行一个主动关闭时,并发回最后一个一个ACK时,该连接在TIME_WAIT状态停留的时间为2倍的MSL,这样在最后的ACK丢失后可以让TCP再次重发(另一端超时并重发最后的FIN)。在连接处于2 MSL等待时,任何迟到的报文段将被丢弃

无论何时关闭一个连接,一端必须保持这个连接,我们看到TIME_WAIT状态将处理这个问题。处理的原则是执行主动打开的一端在进入这个状态时要保持的时间为TCP实现中规定的MSL值的两倍。

2.4 坚持定时器

TCP通过让接收方指定希望从发送方接收的数据的字节数来进行流量控制,如果窗口为0,则会有效阻止发送方发送数据,这里就需要设置TCP的坚持定时器,不断地探查已关闭的窗口,直到窗口被打开或者应用进程使用的连接被终止;

3TCP的超时与重传

TCP提供可靠的运输层服务,它使用的方法就是确认另一端传来的数据,但数据和确认都可能丢失,因此TCP通过在发送时设置一个定时器来解决这个问题。只要当定时器溢出时还没有收到确认,则就重传该数据。实现这个方法的关键就是超时与重传的策略。

3.1往返时间的测量

TCP超时与重传中最重要的一个部分就是对一个给定连接的往返时间的测量。因为路由器与网络流量是会变化的,TCP应该根据这些变化来定义其超时的时间;

首先TCP会测量发出一个报文段和接收到该报文段的确认之间的RTT(Round-TripTime,往返时延),最初的TCP规范使TCP使用低通过滤器来更新一个被平滑的RT T估计器(记为O):R← Rx+ ( 1- x)M(M是新测量得到的值,x是一个平滑因子,推荐为0.9,也就是说每次进行新测量时,原来的时间估计占用09%,新的测量的值占10%)。在使用这个算法的前提下,RFC 793推荐的重传超时时间RTO(Retransmission TimeOut)的值应该设置为:RTO = Ry ,这里的y是一个推荐值为2的时延离散因子。

但在RTT变化范围很大时,就可能会跟不上这种变化,导致不必须的重传,而不必须的重传可能会增加网络的负载。因此还需要跟踪RTT的方差,在往返时间变化很大时,根据均值和方差来计算RTO 。每个RTT测量M的公式。
Err = M-A
A←A + gE rr
D←D + h(|E rr|-D)
RTO = A + 4D
这里的A是被平滑的RT T(均值的估计器)而D则是被平滑的均值偏差。E rr是刚得到的测量结果与当前的RT T估计器差。A和D均被用于计算下一个重传时间( RTO)。增量g起平均作用,取为1 / 8(0 .125)。偏差的增益是h,取值为0.25。当RTT变化时,较大的偏差增益将使RTO快速上升。

3.2 慢启动与拥塞避免

慢启动算法是一个在连接上发起数据流的方法,一开始只允许发送一个报文段,当这个报文段被确认后就可以再发送2个报文段,当这两个报文段被确认后就可以发送4个报文段。(也就是说每收到一个报文段的确认后,可以发送的报文段的大小就+1)。拥塞避免算法是用来处理报文段丢失的方法,报文段丢失有两种情况:超时或接收到重复的确认。 一般在实现中,这两种算法是一起实现来使用的。

拥塞避免算法和慢启动算法需要对每个连接维持两个变量:拥塞窗口(cwnd,congestion window)和慢启动门限(ssthresh,slow start threshold),算法的工作过程如下:

1)对一个连接,初始化cwnd为1个报文段,ssthresh为65535字节;

2)TCP发送的报文段的大小不能超过cwnd和接收方通告窗口的大小,拥塞窗口是发送方使用的流量控制(发送方对网络新状况的估计),而通告窗口则是接收方进行的流量控制(与接收方的缓存大小有关);

3)当拥塞发生时(超时或收到重复的确认),ssthresh被设置为当前窗口的一半(cwnd和通告窗口的最小值,但最少为2个报文段),如果是超时引起的拥塞,则cwnd会被设置为1个报文段(慢启动);

4)当新的数据被确认时,就增加cwnd(当cwnd<ssthresh时,进行慢启动,否则执行拥塞避免算法);慢启动算法的cwnd初始为1,收到一个确认cwnd 就+1,直到cwnd=ssthresh时,后面就进行拥塞避免算法了,拥塞避免算法每次收到确认时,将cwnd 增加1/cwnd;

3.3 快速重传与快速恢复

当我们接收到重复的ACK时,我们不知道是发生的报文段的丢失还是仅仅发生了报文段的重新排序,如果只是收到1到2个重复的ACK,则可能是发生了报文段的重新排序。但如果收到3个以上的重复ACK,就可能是发生了报文段的丢失,于是我们就重传丢失的报文段数据,而不用等待超时定时器的溢出,这就是快速重传算法,接下来执行的是拥塞避免算法而不是慢启动算法,这就是快速恢复算法。这个算法的实现过程如下:

1)当收到第3个重复的ACK时,将ssthresh设置为当前拥塞窗口cwnd的一半。重传丢失的报文段,并将当前拥塞窗口cwnd设置为 ssthresh窗口加上3个报文段大小 ;

2)每次收到另一个重复的ACK时,cwnd增加一个报文段大小,并发送一个分组(如果新的cwnd允许发送);

3)当下一个确认新数据的ACK到达时,设置cwnd为ssthresh的值(恢复到拥塞发生前的水平);

推荐阅读耗子叔的:《TCP的那些事儿(上)》《TCP的那些事儿(下)》

TCP那些事的更多相关文章

  1. [转载] tcp那些事2

    原文: http://coolshell.cn/articles/11609.html 这篇文章是下篇,所以如果你对TCP不熟悉的话,还请你先看看上篇<TCP的那些事儿(上)> 上篇中,我 ...

  2. [转载] tcp那些事1

    原文: http://coolshell.cn/articles/11564.html TCP是一个巨复杂的协议,因为他要解决很多问题,而这些问题又带出了很多子问题和阴暗面.所以学习TCP本身是个比较 ...

  3. 【转】TCP那些事(上,下)

    TCP是一个巨复杂的协议,因为他要解决很多问题,而这些问题又带出了很多子问题和阴暗面.所以学习TCP本身是个比较痛苦的过程,但对于学习的过程却能让人有很多收获.关于TCP这个协议的细节,我还是推荐你去 ...

  4. 计算机网络 学习笔记-传输层:TCP协议简介

    概述: TCP传输前先要建立连接 TCP在传输层 点对点,一条TCP只能连接两个端点 可靠传输.无差错.不丢失.不重复.按顺序 全双工 字节流 TCP报文段 TCP报文段的报头前20字节是固定的,后面 ...

  5. 【图解】你还在为 TCP 重传、滑动窗口、流量控制、拥塞控制发愁吗?看完图解就不愁了

    每日一句英语学习,每天进步一点点: 前言 前一篇「硬不硬你说了算!近 40 张图解被问千百遍的 TCP 三次握手和四次挥手面试题」得到了很多读者的认可,在此特别感谢你们的认可,大家都暖暖的. 来了,今 ...

  6. 一文彻底搞通TCP之send & recv原理

    接触过网络开发的人,大抵都知道,上层应用使用send函数发送数据,使用recv来接收数据,而send和recv的实现原理又是怎样的呢? 在前面的几篇文章中,我们有提过,TCP是个可靠的.全双工协议.其 ...

  7. TCP 重传、滑动窗⼝、流量控制、拥塞控制

    重传机制 TCP 会在以下两种情况发⽣超时重传: 数据包丢失 确认应答丢失 重传超时 重传超时是TCP协议保证数据可靠性的另一个重要机制,其原理是在发送某一个数据以后就开启一个计时器,在一定时间内如果 ...

  8. 《HTTP权威指南》笔记

    http://blog.csdn.net/sunorry?viewmode=contents有些笔记 MIME 类型是一种文本标记,表示一种主要的对象类型和一个特定的子类型,中间由一条斜杠来分隔:te ...

  9. 自己动手开启QUIC(转载)

    源:https://www.bennythink.com/quic.html#title-0 今天在推上偶然发现 Google 在自己的服务器上启用了 QUIC,QUIC 这东西嘛(发音同 quick ...

随机推荐

  1. U3D 打包时找不到tag的问题

    在公司改完一个功能,把工程拷回家打开后,编辑器模式下运行正常,打包PC平台和安卓平台时都报错,找不到chatContent这个tag,察看了下下拉列表中明明有这个tag,并且勾选上了,但是点击add ...

  2. [LeetCode] Word Ladder II 词语阶梯之二

    Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from ...

  3. Spring + SpringMVC + Druid + MyBatis 给你一个灵活的后端解决方案

    生命不息,折腾不止. 折腾能遇到很多坑,填坑我理解为成长. 两个月前自己倒腾了一套用开源框架构建的 JavaWeb 后端解决方案. Spring + SpringMVC + Druid + JPA(H ...

  4. EF使用CodeFirst方式生成数据库&技巧经验

    前言 EF已经发布很久了,也有越来越多的人在使用EF.如果你已经能够非常熟练的使用EF的功能,那么就不需要看了.本文意在将自己使用EF的方式记录下来备忘,也是为了给刚刚入门的同学一些指导.看完此文,你 ...

  5. java使用tomcat7的maven插件发布到服务器

    服务器容器使用tomcat7的maven插件,使用该插件不需要使用tomcat服务器.以下示例均以paycore项目为例. 一.使用tomcat7-maven-plugin 首先在主pom(payco ...

  6. php设计模式--面向对象

    php链式操作的实现: 特点:1.链式操作一般存在于面向对象的情况下链式操作才有意义 /* * SQL语句组合实例类,始发文章web开发笔记 * 学习用,非专业类 * */ class sql{ pr ...

  7. Android基础总结(五)

    HttpClient 发送get请求 创建一个客户端对象 HttpClient client = new DefaultHttpClient(); 创建一个get请求对象 HttpGet hg = n ...

  8. 使用App.config管理数据库连接

    程序的数据库连接字符串可以保持在程序的配置文件App.config中,便于管理. 将配置文件添加至解决方案: 添加连接信息: <?xml version="1.0"?> ...

  9. table里面,怎么根据checkbox选择的一行中的某个单元格的值是否为空,来判断是否该选中

    <table class="stripe" id="tab2"> <tr> <th>选择</th> <th ...

  10. 百度文库下载器 V2.3.4.3 支持豆丁百度文库道客巴巴

    支持豆丁百度文库道客巴巴免下载劵财富值导出word 下载地址: http://pan.baidu.com/s/1qYCmQde