本文内容:

  • TCP的三次握手与四次挥手过程简析
  • TCP的拥塞控制简析
  • UDP与TCP的区别

TCP

https://www.cnblogs.com/lgx-fighting/p/9375858.html

TCP三次握手

过程分析

  1. 首先,客户机与服务器的TCP进程都处于CLOSED(关闭)状态,当要进行TCP连接时,客户机主动打开连接,服务器被动打开连接(这是因为服务请求总是由客户机向服务器发起,因为想要请求的资源都在服务器上,所以客户机想要获取资源就必须主动向服务器发起请求,而不能是等待服务器向自己(客户机)发起请求)。

  2. 然后,服务器的TCP进程先创建传输控制块TCB(传输控制块TCB存储了每一个连接中的重要信息,如:TCP连接表,指向发送和接收缓存的指针,指向重传队列的指针,当前的发送和接收序号,等等),此时,服务器就处于LISTEN(收听)状态。同样的,客户机也会首先创建一个传输控制块TCB发送给服务器。这样,准备工作就做好了。

  3. 客户端->服务端(Listening)

    客户端向服务端发送SYN=1以及seq=x,表明自己想要建立连接,然后发送后客户端就处于SYN-SENT阶段,表名自己已经发送了连接请求

  4. 服务端->客户端

    客户端收到来自客户端的连接请求后,就要回复客户端,设置ACK=1和SYN=1表示自己确认收到连接请求,可以建立连接。同时发送ack=x+1作为自己的确认ack值,同时发送一个新的seq=y,然后自己进入SYN-RCVD状态

  5. 客户端->服务端

    在收到来自服务端的可以连接的回复后,客户端设置设置自己的ACK标志位为1,然后设置自己的ack=y+1,表示自己的确认ack值,如果携带数据,则消耗一个序列,这样客户机下次发送报文段时的序号为x+2不携带数据则seq=x+1,这个来自于第一次客户端向服务端发起请求的seq=x,由于这是第二个包,所以seq=x+1,发送完毕后客户端进入ESTABLISHED状态,服务端接收到客户端发来的第三次握手信息后也进入ESTABLISHED状态

对TCP三次握手的抓包分析:

一些问题

  1. 为什么要三次握手而不是两次握手

    三次握手的目的在于客户端课服务端相互协商好准备发送数据,通过序列号的彼此确认来进行协商

    如果只是两次握手的话,如果客户端向服务端发送连接请求后,服务端向客户端发送自己的应答。按照两次握手的逻辑,服务端认定自己握手成功了,就等客户端发来数据传输信息。但如果服务端的应答信息在传输中丢失了,虽然服务端认为自己握手成功了,但客户端一直没收到这个应答请求,就会认定连接失败了,一直等待服务端的应答,对服务端发送的数据都忽略掉,导致进入死锁。

    在三次握手中,如果客户端向服务端发送的第一次请求没有得到回复,那么客户端将会超时重传

  2. 三次握手中,为什么客户机最后还要再向服务器发送一次确认呢?

    我的想法:

    ​ 这是为了防止已失效的连接请求报文段突然又传到了服务器。所谓“已失效的连接请求报文段”是这样产生的。考虑一种正常的情况,客户机发出连接请求,但因为连接请求报文丢失而未收到确认。于是客户机再重传了一次连接请求,后来收到了确认,建立了连接。数据传输完后,就释放了连接。客户机共发送了两个连接请求报文段,其中第一个丢失,第二个到达了服务器,没有所谓的“已失效的连接请求报文段”。

      但是如果出现了一种异常情况,即客户机发出的第一个报文段并没有丢失,而是在某个节点上长时间滞留了,直至客户机向服务器发送了第二个报文段并且已经完成数据传输释放了连接,此时,第一个报文到达服务器后会被误以为是客户机重新发起的一次连接请求,实质上是一个早已失效的连接请求。如果没有第三次握手,那么这个连接就建立了,但是客户机并不会向服务器发送任何请求,这样连接就会一直持续,白白的消耗网络资源。

    网上答案:

    ​ 如果使用的是两次握手建立连接,假设有这样一种场景,客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。

    如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。

TCP四次挥手

过程分析

  1. 首先客户端向服务端发送FIN=1的数据包,设置seq=u,表明自己想要关闭连接,同时自己进入FIN-WAIT-1状态
  2. 同时这里服务端要表示自己收到了你要关闭连接的请求,发送ACK=1表示自己收到了,ack=u+1作为确认序号,同时这设置seq=v为自己的初始序号,客户端收到这个信息后,自己进入了FIN-WAIT-2状态,处于CLOSE-WAIT状态,客户端在收到服务端发送的这条报文后进入FIN-WAIT-2状态
  3. 然后服务端连续发出报文,设置FIN=1,同时设置ACK=1表示应答,然后ack=u+1,又设置了新的seq=w,这里我其实不是很明白为什么这么麻烦,我感觉可以看做是对客户端发的第一条报文的两次回应
  4. 然后客户端对最后的服务端报文进行回复,回复ACK=1确认,然后设置seq=u+1,我这里认为是自己的发的第二个数据包,这样好记,然后设置ack=w+1,是对服务端最后一个报文的确定,最后服务端关闭了,客户端在等待了2MSL时间后也关闭

一些问题

时间为什么是2MSL?

​ 在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。

​ client再发送完最后一个报文端ACK之后,再经过2MSL的时间,就可以是本次连接持续时间内的所有产生的报文段都消失,这样下一次连接中就不会出现旧的请求连接报文段。

为什么是四次挥手?

​ 因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,”你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

完整的一次TCP连接

这里我个人认为挥手的包与之前上文分析的不一样,可能在于他把ACK、FIN包给合并了

所以实际上发了3个挥手数据包

TCP拥塞控制

https://blog.csdn.net/qq_41431406/article/details/97926927

其实我感觉这个问题,直接说的话说不明白,直接看图倒是十分清晰

TCP的拥塞控制一般分为四种办法:

  • 慢开始
  • 拥塞控制
  • 快重传
  • 快回复

名词解释:

  • cwnd – 拥塞窗口

  • ssthresh(slow start threshold)– 慢启动到拥塞避免到阈值

  • RTT——Round Trip Time,也就是一个数据包从发出去到回来的时间

  • RTO(Retransmission TimeOut)重发超时时间

慢开始与拥塞避免

为了防止cwnd增长过大引起网络拥塞,还需设置一个慢开始门限ssthresh状态变量。ssthresh的用法如下:

  • 当cwnd<ssthresh时,使用慢开始算法。
  • 当cwnd>ssthresh时,改用拥塞避免算法。
  • 当cwnd=ssthresh时,慢开始与拥塞避免算法任意。

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

无论是在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(其根据就是没有收到确认,虽然没有收到确认可能是其他原因的分组丢失,但是因为无法判定,所以都当做拥塞来处理),就把慢开始门限设置为出现拥塞时的发送窗口大小的一半。然后把拥塞窗口设置为1,执行慢开始算法。

快重传和快恢复

​ 快重传要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方)而不要等到自己发送数据时捎带确认。快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期。

快重传配合使用的还有快恢复算法,有以下两个要点:

  • 当发送方连续收到三个重复确认时,就执行“乘法减小”算法,把ssthresh门限减半。但是接下去并不执行慢开始算法。
  • 考虑到如果网络出现拥塞的话就不会收到好几个重复的确认,所以发送方现在认为网络可能没有出现拥塞。所以此时不执行慢开始算法,而是将cwnd设置为ssthresh的大小,然后执行拥塞避免算法。
  • 这里写一下我的看法:他虽然没说是怎么判断M3未到达,但我猜测是根据seq不连续,导致M3seq出现断层,从而接受方认为出现了包丢失,从而重复确认前一个包

我觉得挺好理解的,就是一个包丢了,发送方再次发送三个数据包收到回应都是丢包之前的最后一次确认包,说明不是拥塞了,而是丢包了,就把cwnd和阈值设置为之前的一半,然后执行拥塞避免,就是又+1、+1

UDP

TCP与UDP的区别

https://zhuanlan.zhihu.com/p/24860273

1、基于连接与无连接;

2、对系统资源的要求(TCP较多,UDP少);

3、UDP程序结构较简单;

4、流模式与数据报模式 ;

5、TCP保证数据正确性,UDP可能丢包;

6、TCP保证数据顺序,UDP不保证。