计算机网络读书笔记-----UDP vs TCP

时间:2021-10-15 14:34:21
  • UDP:

UDP用户数据报协议在IP数据报服务上只增加了分用复用和差错检测的功能。
UDP是不具有可靠性的数据报协议。

  • UDP的特点:

UDP是无连接的;
UDP不保证可靠交付,即尽最大努力交付
UDP是面向报文的:

  发送方的UDP对应用程序交下来的报文,在添加首部后就直接交付给IP
  层。对应用层交下来的报文,既不拆分也不合并,而是保留这些报文的
  边界。对IP层交上来的UDP数据报,在去除首部后就直接交给上层的应
  用进程,所以说UDP数据报一次交付一个完整的报文。如图所示:

计算机网络读书笔记-----UDP vs TCP

UDP没有拥塞控制。
所以网络出现的阻塞是不会影响发送方的速率的,因此对于某些实时应用来说很重要,但是正因为这一点,很多源主机都向网络中发送高速率的实时数据流,网络中很可能出现阻塞,结果就是大家都收不到数据,更加阻塞。
UDP支持一对一,一对多,多对多的交互通信
UDP的首部开销小,只有8个字节,而TCP的首部有20个字节

  • UDP数据报格式:
    计算机网络读书笔记-----UDP vs TCP

我们可以看到UDP首部只有四个字段,每个字段2字节,共8个字节。

源端口:源端口号。
目的端口:目的端口号。
长度:UDP用户数据报的长度,最小8个字节(仅有首部)
检验和:用来检验UDP在传输过程中是否出错,若出错,直接丢弃。

注意到在UDP数据报的前方还有个虚线化的伪首部。

UDP在计算检验和的时候,要在UDP的数据报前面增加12个字节的伪首部。
伪首部,就不是真正的首部,只是在计算检验和的时候,加到用户数据报的
前面组成的一个临时的UDP数据报,检验和就是根据这个临时的数据报进行
检验的。

UDP的检验和和IP的类似,只是IP的检验和只检验IP的首部,而UDP的检验和要检验首部和数据部分。

首先是将检验和字段全部置0,将UDP数据报的二进制看成许多的16位拼接起
来,不够的加0填充,然后按照二进制反码计算和,将此和写入检验和;在接
收方,将UDP的数据报(伪首部+首部+数据)的二进制16位进行求和,若全
为1,则表示无差错。具体流程见下图:

在发送方:
计算机网络读书笔记-----UDP vs TCP

接收方类似进行二进制反码运算求和是 1111 1111 1111 1111


  • TCP

TCP是TCP/IP体系中最复杂的一个协议,提供全双工和可靠的协议。
TCP与UDP的最大的区别就是TCP是面向连接的,而UDP是无连接的。
TCP是面向连接、具有可靠性的流协议。

  • TCP特点:

面向连接的运输层协议:
传输数据前必须先建立连接,数据传输完成之后释放连接。
每一条TCP的连接只能有两个端点,也就是说TCP连接是一对一的
可靠:TCP提供可靠交付的服务,也就是说数据在传输过程中可以做到无差错,不丢失, 不重复,并且按序到达。

提供全双工通信:
TCP允许通信的双方在任何时候都可以发送数据,TCP连接的两端都设有发送缓存和接收缓存。在发送时,应用进程将数据发送到TCP的发送缓存中后就可以去办自己的事情,TCP在合适的时候将数据发送出去;接收时,TCP把收到的数据放入缓存,上层的应用进程在合适的时候取出缓存中的数据。
面向字节流:
UDP是面向数据报的,我们容易理解,但是面向字节流就有点复杂了。
这里的流是指:流入进程或从进程中流出的字节序列。

所谓的面向字节流是说:虽然应用程序和TCP交互时,传输的都是大小不等
的数据块,但是TCP把应用进程交下来的数据看成是一连串的无结构字节
流,TCP并不知道字节流的含义。接收方的应用程序必须可以识别所传送的
字节流,可以将其还原成应用层有意义的数据。

图解TCP的面向字节流:
计算机网络读书笔记-----UDP vs TCP

可以看出TCP和UDP的发送报文采用的方式是完全不同的,TCP不关心应用进程一次将多少个字节放入TCP的缓存,TCP会根据窗口值和拥塞程度决定一个报文段中包含多少个字节,而UDP发送的报文长度是应用进程给出的。

  • TCP数据报格式:

TCP虽然是面向字节流的,但是TCP传输单元是报文段,一个TCP报文段又分为首部和数据部分,而且TCP的全部功能都体现在首部各字段的作用。

先看一下TCP数据报的格式:
计算机网络读书笔记-----UDP vs TCP
TCP报文段首部的前20个字节是固定的,所以最小TCP的首部就是20字节。

源端口和目的端口
和UDP类似表示源端口号和目的端口号,TCP的分用也是通过端口实现的。

序号
序号占4个字节,所以范围是[0,2^32 -1],共2^32 个序号,当增加到最后一位的时候又会从0开始(即mod2^32 )。TCP是面向字节流的,在TCP传送的每一个字节都按照顺序编号。整个数据的初始序号在TCP建立连接的时候设置,首部中序号字段的值是指本报文段所发送的数据的第一个字节的序号。例如:一段报文的序号字段时301,携带100字节的数据,所以最后一个字节的序号是400,也就是说,下一个报文段的数据序号应当从401开始。

确认号
占4个字节,表示期望收到对方的下一个报文段的数据的第一个字节的序号。例如主机B收到主机A发送过来的一个报文段,序号字段是501,数据长度是200,表明主机B收到了A发送的到序号700为止的数据,期望下一次收到的数据序号是701,所以把确认序号改为701。所以说:确认号为N,则表示正确收到了到序号N-1为止的数据。

因为确认序号长度为32位,可以对4G的数据进行编号,所以当重复使用的时候,旧的数据早已经到达了网络的终点。

TCP传输的可靠是由于使用了序号和确认,当TCP发送一段报文时,它同时也在自己的重传队列中存放一个副本,若收到确认删除次副本,若计时器时间到之前没有收到数据,则重传数据。TCP的确认并不保证数据已由应用层交付给了端用户,而只是表明在接收端的TCP收到了对方所发送到报文段。

数据偏移
占4位,是指TCP报文段的数据起始位置距离TCP报文段的起始位置的距离,即TCP首部的长度。

保留:占6位,为以后使用,目前应置0。

6个控制位:
紧急比特URG
当URG=1时,表明紧急指针字段有效。告诉系统此报文段中有紧急数据,应尽快传输,而不要按照排队的顺序来传送。
比如说,执行了一长串的程序,后来想取消,用键盘发出中断命令Ctrl+C,如果不用紧急数据,这两个字符会排在TCP缓存的末尾。前面的数据处理完才会中断。当紧急比特位置1时,TCP将这两个字符插入到报文段的最前面,其后面的数据是普通数据。这时需要与首部中的紧急指针字段配合使用。

确认比特ACK:
当ACK=1时,表名确认号字段有效,ACK=0时,确认号字段无效。TCP规定,在连接建立以后所有传输的报文段都应该把ACK置1。

推送比特PSH:
当两个应用进程进行交互式的通信时,,一端希望在键入一个命令后立即就可以收到对方的响应,此时TCP就可以使用推送操作。发送方TCP将PSH置为1,并立即创建一个报文段发送出去,接收方TCP发现PSH是1,就将报文尽快的交付给应用程序,而不用等到整个缓存都填满了才交付。

复位比特RST:
当RST=1时,表示TCP连接中出现了严重的错误(主机崩溃或其他原因),必须释放连接,然后重新建立连接。同时RST=1还可以用来拒绝一个非法报文段或拒绝一个连接。

同步比特SYN:
在连接建立时用来同步序号,当SYN=1,ACK=0时,表示这是一个连接请求报文段,如果对方同意建立连接,在响应报文段中应该讲SYN=1,ACK=1。

终止比特FIN:
用来释放一个连接。当FIN=1时,表示此报文段的发送分的数据已经传输完毕,要求释放连接。

窗口:
占两个字节,范围是[0,2^16 -1]。表示发送本报文的一方的接收窗口,是说明从本报文段的确认号算起,最多还可以接收多少个数据。因为接收方的数据缓存是有限的,所以窗口值说明了允许发送方发送的数据量。同时接收窗口也是发送方设置发送窗口的依据。

检验和:
方法类似UDP的检验和,在计算检验和时应该加上伪首部,伪首部的格式根UDP一样,但要注意UDP和TCP的协议号不一样(第四位)。

紧急指针:
紧急指针字段仅在URG=1时有效,紧急指针指向的是紧急数据在报文段的最后一个字节的位置。紧急数据处理完成后,TCP通知应用程序恢复到正常操作。注意窗口值为0的时候,也可以发送紧急数据。

选项:长度可变,最长可达40字节。
TCP最初的时候只规定了一种选项:
最大报文段长度MSS:是指每一个TCP报文段中数据字段的最大长度,所以是TCP报文段的长度减去TCP的首部长度。
随着因特网的发展,又增加了许多选项:窗口扩大、时间戳,选择确认

时间戳:
时间戳选项用于对高速通信中对序列号的管理的,若要将几个G的数据高速转发到网络中,32位的序列号可能很快用完。网络不稳定的环境下,很可能很早发送的序号很晚却收到,所以接收端对新老序号很容易产生混淆,从而无法可靠传输,为了避免这个问题,引入时间戳,可以区分新老序号。

选择确认:
若收到的报文段无差错,只是中间少一部分序号,收到的序号间断,不连续。那么可以通过选择确认选项让发送方只传送缺少的数据,而不重新传送已经正确到达接收方的数据。避免无用重发,同时提高了速度。但是最多允许四次这种状态的确认应答。

窗口扩大:
是改善TCP吞吐量的选项,TCP首部的窗口字段只有16位,也就是说在往返时间内,最多只能传送64K的数据,但是如果采用此选项,最大值可以扩展到1G字节,所以在往返时间较长的情况下,也可以保持较高的吞吐量。

  • TCP可靠的基础:

我们在数据链路层的可靠性那一章中阐述了停止等待协议和连续ARQ协议
当初网络的初期,通信不可靠,这两者便是可靠的基础。

  • TCP怎么实现可靠性:

    TCP有很多机制实现可靠性,下面我们来讲几种:

    以字节为单位的滑动窗口:

关于滑动窗口的概念,我们在数据链路层已经做了很多的铺垫,现在来看看TCP的滑动窗口,TCP的滑动窗口是以字节为单位的,在收到B发来的报文段时,获取其接收窗口中的字段(20字节),确认号是31,表示B期望收到的下一个序号是31,从而A构造出自己的发送窗口
计算机网络读书笔记-----UDP vs TCP

这个发送窗口表示:在没有收到B的确认的情况下,可以连续将窗口内的所有数据都发送出去,凡是没有收到确认的数据,都要保留,为后面的超时重传做准备。
显然,窗口越大,在收到B的确认前,可连续发送的就越多。

发送窗口的位置由前沿和后沿的位置共同确定。发送窗口后沿变化情况有两种可能:
不动(没有收到新的确认)和前移(收到了新的确认),但是后沿不可能向后移动,因为不能撤销掉已经接收到的确认。
前沿通常是向前移动,但也可能不动,对应于没有收到新的确认,对方通知的窗口大小也不变;收到了新的确认,但对方通知的窗口缩小了。
TCP标准不允许前沿向后收缩,因为很可能在对方通知的窗口缩小之前,已经发送了窗口中的数据,现在又不让发送,会产生一些错误。

现在假设A发送了序号31~41的数据,这时由于没有收到确认,发送窗口的位置并没有改变,如图,31~41序号的数据(深红色)就变成了已发送未收到确认的,后面粉红色的数据是可用窗口,表示允许发送,但未发送。
计算机网络读书笔记-----UDP vs TCP

我们发现,有三个指针在确定着滑动窗口的状态。

P3 - P1 = A的发送窗口
P3 - P2 = A的可用窗口,即允许发送但未发送的字节数
P2 - P1 = 已经发送但未收到确认的字节数

接着A都发送了,那么下来总该接收了,来看看B的接收窗口。
刚才我们说过了B的接收窗口是20,因为A的发送窗口是依据B的接收窗口的大小来构造的。
如图:
计算机网络读书笔记-----UDP vs TCP

B接收到了序号为32,33的数据,但是没有收到31序号的数据(丢失或者滞留在网络中),
所以此时,B只能对按序收到得到数据中的最高序号给出确认,因此B发送的确认报文段中的确认号仍是31。

假设B此时收到了序号为31的数据,把这些序号的数据交付给主机,然后B删除这些数据。接着把接收窗口向前移动三个序号,同时给A发出确认,确认号为34,如图,我们发现B还接收到了序号为37、38、40的数据,但是没有按序到达,只能暂存在接收窗口中。

计算机网络读书笔记-----UDP vs TCP

此时A收到了B的确认,确认号为34,表明34序号之前的数据已经正确收到,期望下一次收到的序号是34,A的发送窗口向前移动3个序号,注意指针P2不动,可用窗口增大了。

计算机网络读书笔记-----UDP vs TCP
现在A将42~53之间的数据全部发送,此时指针P2和指针P3重合,可用窗口为0发送窗口已满,因此必须停止发送,如图:

计算机网络读书笔记-----UDP vs TCP

B接收到A发送过来的数据,并向A发送确认,但是这些确认都滞留在网络中,为了保证可靠传输,A只能认为B还没有接收到这些数据,A过一段时间后(超时计时器控制)就重传这部分数据,并重置超时计时器,直到收到B的确认,A的窗口继续向前滑动发送新的数据。

缓存与窗口

前面我们提到缓存,发送发把应用进程中的字节流放入TCP缓存,而接收方在缓存中读取字节流。进一步说明缓存和窗口的关系。

注意:缓存空间和序号窗口都是有限的,所以都是循环使用的。

发送缓存用来暂时存放:发送应用程序传送给发送方TCP准备发送的数据和TCP已经发送但未接收到确认的数据。

计算机网络读书笔记-----UDP vs TCP

图中可以看出发送窗口只是发送缓存中的
已确认的数据应该从发送缓存中删除,所以发送窗口的后沿和发送缓存的后沿是重合的。
发送应用程序最后写入的字节减去最后被确认的字节,就是保留在发送缓存中的字节数。

接收缓存用来暂时存放:
按序到达的、但尚未被接收应用程序读取的数据。
未按序到达的数据。
计算机网络读书笔记-----UDP vs TCP

图中说明如果应用程序来不及处理读取接收缓存中的数据,接受缓存就会被填满。

对不按序到达的顺序如何处理?
当然是不能丢弃的,网络资源会浪费很多,TCP通常对不按序到达的数据,是先暂存到接收窗口中,等到字节流所缺少的字节收到后,再按序交付给应用进程。

超时重传:

我们经常提到,TCP发送方在规定的时间内没有收到确认就重传已发送的报文段,但是这种重传的时间如何选择?

最理想的情况是找一个最小的时间,确认应答一定能在这个时间内返回。
但是这个时间的长短会随着数据包途径的网络环境不同而不同,比如在高速的LAN中响度较短,而在长距离的通信中较长一些。

TCP在每次发包的时候都会计算往返时间及其偏差,将这个往返时间和偏差相加,重发超时时间就是比这个总和要稍大一点的值。
之所以会统计这两个值是因为网络环境不同,往返时间可能会产生大幅度的摇摆,因为有时候数据包的分段是经过不同线路到达的。

在Window系统中,超时都以0.5秒为单位进行控制,因此重发超时都是0.5的整数倍。由于最初的数据包还不知道往返时间,所以其重发超时一般设置为6秒左右。

  • TCP流量控制

如果发送方发送的数据过快,接收方有可能来不及接收,这就会造成数据的丢失。
所谓流量控制就是让发送方不要发的太快,要让接收方来得及接收。

流量控制是基于窗口实现的,接收端向发送端主机通知自己可以接受数据的大小,即窗口大小,发送端发送的数据不会超过窗口的限度。

窗口值越大,说明网络吞吐量越高
但是接收端的这个缓冲区一旦面临数据溢出,窗口大小的值也会随之被设置为一个更小的值通知发送端,从而控制数据流量。
实例:
A向B发送数据。在连接建立时,B高速A,B的接收窗口是4000字节

计算机网络读书笔记-----UDP vs TCP

可以看出B在接收完前4000个字节后,窗口为0,缓冲区已满,所以需要暂时停止接收数据,此时发送方必须等到窗口更新通知后,才可以继续进行通信。
但是如果这个窗口的更新通知在传送途中丢失,则可能导致无法通信,
所以TCP为每一个连接设有一个持续计时器。只要连接中的一方收到了对方零窗口通知,就启动持续计时器。若持续计时器的时间到了,就发送一个零窗口探测报文段(仅携带1字节的数据),对方就在确认这个探测报文段时给出了现在的窗口值,如果窗口值仍然是0,那么收到这个报文段的一方重指计时器,如果不是0,就可以进行通信了。

  • 提高网络传输速率:

可以用不同的机制来控制TCP报文段的发送时机。
第一种:TCP维持一个变量,其值等于MSS最大报文长度,只要缓存中的数据达到MSS字节时,就组装成一个TCP报文段发送出去。
第二种:发送方的应用进程指明要发送报文段,即TCP支持的推送操作。
第三种:发送方的一个计时器期限到了,这时就把当前已有的缓存数据装入报文段(长度不能超过MSS)发送出去

可以推迟应答和捎带应答。

当连接为TCP连接,设用户只发一个字符。加上20字节的首部得到21字节的TCP报文段,再加上20字节的IP首部,形成41字节长的IP数据报,在局域网上这些分组通常不会引起麻烦,但是广域网上,小分组则会增加拥塞出现的可能。可以采用Nagle算法:
Nagle算法:

    若发送应用进程把要发送的数据逐个字节的送到TCP的发送缓存,则发
送方就把第一个数据字节先发送出去,把后面到达的数据字节缓存起
来。当发送方收到对第一个数据字节的确认后,再把发送缓存中的所有
数据组装成一个报文段发送出去,同时继续对随后到达的数据进行缓
存。只有在收到对前一个报文段的确认后才继续发送下一个报文段。

同时Nagle该规定,当到达的数据已达到发送窗口大小的一半或已达到报文段的最大长度时,就立即发送一个报文段。

糊涂窗口综合症:

    TCP的缓存已满,而接收方的应用程序一次只从接收缓存中读取一个字
节,然后向发送方发送确认,因为接受窗口是1,所以发送方只能发送
一个字节的数据,这样持续下去,网络的效率会很低。

为了避免这个问题:我们可以让接收方等待一段时间,使得接收缓存有足够空间可以容纳一个最长的报文段,或者等到接收缓存已有一半的空闲时间。只要出现这两种情况的一种,接收方就发出确认报文,同时发送方也不要发送太小的报文,可以将数据累积成足够大的报文段,或者达到接收缓存空间的一般大小。

  • TCP拥塞控制:

何为拥塞,对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏,这种情况就叫拥塞。出现拥塞后,网络中的资源供应不足,整个网络的吞吐量就会随输入负荷的增大而下降。

对此提供的策略便是拥塞控制:
拥塞控制就是防止过多的数据注入网络中,这样就使得网络中的路由器或链路不致过载。
拥塞控制的前提是网络能够承受现有的网络负荷。

拥塞控制和流量控制的区别:
拥塞控制是一个全局性的过程,涉及到所有的主机,所有的路由器,以及与降低网络传输性能有关的所有因素。
而流量控制往往是点对点通信量的控制,是一个端到端的问题。

几种拥塞控制的方法:
慢开始、拥塞避免、快重传和快恢复。

这里介绍慢开始和拥塞避免的工作原理:

当主机开始发送数据时,如果立即把大量的数据字节注入网络,那么就有可能引起网络拥塞,因为还不清楚网络负荷的情况。
所谓慢开始,就是由小到大的逐渐增大发送窗口,也就是说从小到大增大拥塞窗口数值。

在慢开始时,将这个拥塞设置为最大报文段MSS的数值,每收到一个对新的报文段的确认后,拥塞窗口的值就加1。如下图所示:

计算机网络读书笔记-----UDP vs TCP

这里我们首先将拥塞窗口cwnd置为1,发送完一个报文段M1,而且收到接收方发来的确认时,将cwnd增大到2,然后发送M2,M3,再次接收到确认后,将cwnd增加到4。因此,每经过一个传输轮次,拥塞窗口就加倍。

Ps:传输轮次:把拥塞窗口cwnd所允许发送的数据全部发送出去,并且收到
了对最后一个字节的确认。可以看出就是整个报文段的往返时间。

为了防止拥塞窗口增长过大,引起网络阻塞,所以还需要设置一个慢开始门限ssthresh

当cwnd < ssthresh时,使用上述的慢开始算法
当cwnd > ssthresh时,停止使用慢开始算法而改用拥塞避免算法
当cwnd = ssthresh时,既可以使用慢开始算法,也可使用拥塞避免算
法。

拥塞避免算法的思路是让cwnd缓慢得增大,即每经过一个RTT往返时间就把发送方的拥塞窗口cwnd加1,而不是加倍。这样,拥塞窗口cwnd按线性规律缓慢增长,比慢开始增长速率慢的多。

无论在哪个阶段,只要发送方判断网络中出现拥塞(没有按时收到确认),就要把慢开始门限ssthresh置为出现拥塞时发送窗口的一半,然后将cwnd置1,重新执行慢开始算法。
(这样做就可以使发生拥塞的路由器把缓存中积压的分组处理完毕)

例子:
计算机网络读书笔记-----UDP vs TCP

图中的单位是报文段的个数,而不是字节。横坐标是传输轮次。

1、在开始的时候将拥塞窗口置为1,慢开始门限的初始值ssthresh设置为
16
2、在执行慢开始算法时(流程见上文),拥塞窗口cwnd随着传输轮次按指
数增长,超过慢开始门限值时(cwnd=16),开始执行拥塞避免算法,拥塞
窗口按照线性规律增长。
3、假设拥塞窗口增长到24时,网路出现超时,很可能拥塞,所以慢开始门
限值变为原来的一般(12),拥塞窗口置为1,并执行慢开始算法,当拥塞
窗口再次达到门限值时,改为拥塞避免算法。

加法增大乘法减小(AIMD算法)
所谓的乘法减小(Multiplicative Decrease)就是当出现网络拥塞时,就把慢开始的门限值ssthresh减半,然后执行慢开始算法。
而加法增大(Additive Increase)是执行拥塞避免算法时,使拥塞窗口缓慢增大,以防止网络过早出现拥塞
这两者合起来称为AIMD算法

这里的方法并不能完全避免拥塞,那时不可能的,这只是是网络不容易出现拥塞。


  • TCP运输连接管理:

TCP运输连接有三个阶段:连接建立,数据传送,连接释放。

TCP在连接建立过程中要解决三个问题:

双方都知道另一方的存在;
允许双方协商一些参数(最大窗口值、时间戳选项、服务质量等);
能够对运输实体资源(缓存大小,连接表中的项目)进行分配。

TCP建立连接:
大概都听过三次握手,可是三次握手到底是怎么握的呢,下面来解析一下:

TCP的连接建立都是采用客户服务器方式,主动发起请求建立连接的是客户,被动等待建立连接的是服务器。

服务器进程运行在主机B上,客户进程运行在主机A上。

服务器进程先发出一个被动打开命令,告诉它的TCP准备接受客户进程的连接请求,此时服务器进程就处于监听状态,检测有发送连接请求的客户进程,如果有,则响应。
客户进程主机A的TCP发送一个主动打开命令,表示现在要和某个IP地址的某个端口建立连接。

此时主机A的TCP向主机B的TCP发出连接请求报文段,这时候首部的同步比特SYN置为1,同时选择一个初始序号seq=x,完成后主机A处于同步已发送状态。
主机B接收到主机A发送过来的报文,发现同步比特SYN位为1,就知道主机A要求建立连接,主机B同意建立连接后,返回一个响应报文段,首部的同步比特SYN和确认比特都置为1,同时确认号为主机A的初始序号+1(ack=x+1),主机B还要为自己选择一个初始序号作为序号字段(seq=y),此时主机B处于同步收到状态。
主机A收到主机B的报文段后,还要给B发送一次确认,确认号为服务器的初始序号+1(ack=y+1),序号为第一次发送的序号+1,因为SYN置1的报文段不能携带数据,但要消耗一个序号,ACK置1的报文段不携带数据则不消耗序号,这时A的TCP通知其上层应用进程,TCP连接已经建立,A处于已建立连接状态。
B收到A的确认后,也进入已建立连接状态。

计算机网络读书笔记-----UDP vs TCP

主机A最后为什么还要发送一次确认?

    防止已失效的连接请求报文段。

如果是两次握手的话:
如果主机A第一次发送给主机B的请求报文段1在网络中停滞阻塞了,以至于延误到连接释放后的某个时间才到达B,主机B并不知道是失效的,所以误以为主机A是要重新建立一次新的连接,于是向A发出确认报文段,表示同意建立连接。但是因为此时主机A并没有请求建立连接,所以不会理会B发过来的确认,B却以为新的连接已经建立了,就一直处于等待状态,浪费了网络的资源。

如果是三次握手的话,A不会给B的确认发送确认,B收不到A发送的确认,就知道A没有请求建立连接。

第一次握手:服务端知道客户端能发信息
第二次握手:客户端知道服务端能收数据,也能发数据
第三次握手:服务端知道客户端能收数据

如果第三次A的报文段丢失?
网上找到的答案:

    如果客户机到服务器的ACK报文段丢失(相应于三次握手的第三次),
链接仍能正常工作这是因为客户端已经处于ESTABLISHED状态,所以
应用进程可以向另一方发送数据每个报文段都有ACK标志置位,而且为
正确数据,所以第一个报文段到达服务器时,服务器也也转移到
ESTABLISHED状态这就是在说三次握手协议的第三次只是保证正确用
的,意义不像前两次一样大,可以丢失。
  • TCP释放连接:

由于TCP是全双工通信,所以通信的双方都需要释放连接,来回一共四次。也称四次挥手。

数据传输结束后,双方都可以释放连接,现在A和B都处已建立连接状态。
A的应用进程首先向其TCP发出连接释放报文段,并停止发送数据,然后主动关闭TCP连接。在报文段中,终止比特FIN位置为1,序号为前面已经传送过的数据的最后一个字节的序号+1(seq=u),这时A进入终止等待-1状态,等待B的确认。

B收到连接释放报文段后,给A要返回响应报文段,首部的ACK=1,seq等于自己前面传送过的数据的最后一个字节+1(seq=v),ack=u+1,B进入关闭等待状态,此时TCP服务器进程通知应用程序,从A到B这个方向的连接就释放了,此时TCP连接处于半关闭状态。

A收到B的确认后,进入终止等待-2状态,等待B发送的连接释放报文段。

B已经没有数据要给A发送,B的应用进程就通知TCP释放连接,此时B发出的连接释放报文段将FIN置为1,序号为seq=w(在半连接状态有可能发送了数据),但是ack还应该是上次已经发送过的确认号(ack=u+1),这时候B进入了最后确认阶段,等待A的确认。

A收到B的连接请求释放报文后,必须对此发出确认。在确认报文段中将ACK置1,seq为u+1(因为FIN类似SYN都要消耗一个序号),确认号是ack=w+1。然后进入时间等待状态,现在TCP还没有释放掉,必须经过时间等待计时器设置的时间2MSL(MSL称为最长报文段寿命)后,A才进入到关闭状态。
计算机网络读书笔记-----UDP vs TCP

为什么A发送完确认还要在等待2MSL的时间呢?

1、为了保证A发送的最后一个确认报文段可以到达B。

如果最后一次的报文丢失,B长时间接收不到对自己FIN+ACK报文的确认,
就会重发FIN+ACK报文,这样A就可以在2MSL接收到B重传的这个报文,A对
此重新发送一次确认,重新启动2MSL计时器,最后A、B都进入关闭状态。如
果不等待,那么B收不到确认,无法按照正常步骤使B进入关闭状态。

2、A等待的2MSL,就可以使所有在本次连接中产生的报文段都从网络中消失,这也就防止了上面的已失效的连接请求报文段出现在下一次新的连接中


保活计时器:

当主机A与主机B建立好连接后,主机A突然出现故障,崩溃之类的,所以不能让主机B一直等下去,这时候就用到了保活计时器,主机B没接收到一次主机A发送来的数据,就会重新设置一次保活计时器,一般为两小时,如果超过了两个小时,主机B还没有收到主机A发送的消息,主机B就会向主机A发送一条探测报文段,每隔75分钟发一次,当发送到10次时,主机A没有响应,就认为出故障而自动断开连接。

摘自:
计算机网络.第五版.谢希仁
参考:
TCP/IP详解卷一
图解TCP/IP