tcp状态转移图,各个状态;tcp可靠性

三次握手四次挥手状态转移图:
在这里插入图片描述Connect发起链接时三次握手
Cli (SYN-SENT) --------> SYN --------> ser
<--------ACK.SYN <--------(SYN_RECVIVED)
(ESTABLISHED)-------->ACK------>(ESTABLISHED)
客户端对服务器说:你可以我建立连接吗?(然后进入等待服务器回话)
服务器回答说:可以,你可以也和我建立链接吗?
客户端回答说:可以
四次挥手:
Cli (FIN_WAIT_1)---------->FIN------------->ser
(FIN_WAIT_2)<---------ACK---------(CLOSE_WAIT)
(TIME_WAIT)<---------SYN---------(LAST_ACK)
----------->ACK---------(CLOSED)
客户端对服务器说:我要和你断开连接了
服务器说:好的,我知道了
服务器说:我也要和你断开连接了
客户端说:好的,我知道了

各个状态:
LISTEN - 侦听来自远方TCP端口的连接请求;
SYN-SENT -在发送连接请求后等待匹配的连接请求;
SYN-RECEIVED - 在收到和发送一个连接请求后等待对连接请求的确认;
ESTABLISHED- 代表一个打开的连接,数据可以传送给用户;
FIN-WAIT-1 - 等待远程TCP的连接中断请求,或先前的连接中断请求的确认;
FIN-WAIT-2 - 从远程TCP等待连接中断请求;
CLOSE-WAIT - 等待从本地用户发来的连接中断请求;
CLOSING -等待远程TCP对连接中断的确认;
LAST-ACK - 等待原来发向远程TCP的连接中断请求的确认;
TIME-WAIT -等待足够的时间以确保远程TCP接收到连接中断请求的确认;

TIMEWAIT状态的原因:
(1)当由主动关闭方发送最后的ACK丢失并导致被动关闭方重发FIN时,TIME_WAIT维护连接状态。
延长了TCP对当前连接的维护信息,对于正确处理连接的正常关闭过程中确认报文丢失很有必要
(2)处理掉之前未发送到的数据 防止与新连接的数据混在一起
time_wait状态是什么
简单来说:time_wait状态是四次挥手中服务器向客户端发送FIN终止连接后进入的状态 。到time_wait状态存在于客户端收到服务器Fin并返回ack包时的状态
当处于time_wait状态时,我们无法创建新的连接,因为端口被占用。

为什么会有time_wait状态
time_wait存在的原因有两点
1.可靠的终止TCP连接。
2.保证让迟来的TCP报文段有足够的时间被识别并丢弃。
1.可靠的终止TCP连接,若处于time_wait的客户端发送给服务器确认报文段丢失的话,服务器将在此重新发送FIN报文段,那么客户端必须处于一个可接收的状态就是time_wait而不是close状态。
2.保证迟来的TCP报文段有足够的时间被识别并丢弃,linux 中一个TCP端口不能打开两次或两次以上,当客户端处于time_wait状态时我们将无法使用此端口建立新连接,如果不存在time_wait状态,新连接可能会收到旧连接的数据。time_wait持续的时间是2MSL,保证旧的数据可以丢弃,因为网络中的数据最大存在MSL(maxinum segment lifetime)

3.哪一方会有time_wait状态
time_wait状态是一般有客户端的状态。而且会占用端口
有时产生在服务器端,因为服务器主动断开连接或者发生异常

4.如何避免time_wait状态占用资源
如果是客户端,我们一般不用担心,因为客户端一般选用临时端口,再次创建连接会新分配一个端口。除非指定客户端使用某端口,不过一般不需要这么做。
如果是服务器主动关闭连接后异常终止,则因为它总是使用用一个知名服务器端口号,所以连接的time_wait状态将导致它不能重启,不过我们可以通过socket的选项SO_REUSEADDR来强制进程立即使用处于time_wait状态的连接占用的端口。
通过socksetopt设置后,即使sock处于time_wait状态,与之绑定的socket地址也可以立即被重用。
此外也可以通过修改内核参数/proc/sys/net/ipv4/tcp_tw/recycle来快速回收被关闭的socket,从而是tcp连接根本不进入time_wait状态,进而允许应用程序立即重用本地的socket地址。
CLOSED - 没有任何连接状态;

tcp拥塞控制
a.慢启动阶段(slow start):发送方一开始便向网络发送多个报文段,直至达到接收方通告的窗口大小为止。当发送方和接收方处于同一个局域网时,这种方式是可以的。但是如果在发送方和接收方之间存在多个路由器和速率较慢的链路时,就有可能出现一些问题。一些中间路由器必须缓存分组,并有可能耗尽存储器的空间。
b.拥塞避免阶段(congestion avoidance):当发现超时或收到3个相同ACK确认帧时,则表示有丢包事件,此时网络已发生拥塞现象,此时要进行相应的拥塞控制。将慢启动阈值设置为当前拥塞窗口的一半;如检测到超时,拥塞窗口就被置为l。如果拥塞窗口小于或等于慢启动阈值,TCP重新进人慢启动阶段;如果拥塞窗口大于慢启动阈值,TCP执行拥塞避免算法。
c.快速重传阶段(fast retransmit):当TCP源端收到到三个相同的ACK副本时,即认为有数据包丢失,则源端重传丢失的数据包,而不必等待RTO超时。同时将ssthresh设置为当前cwnd值的一半,并且将cwnd减为原先的一半。
d.快速恢复阶段(fast recovery) :当"旧"数据包离开网络后,才能发送"新"数据包进入网络,即同一时刻在网络中传输的数据包数量是恒定的。如果发送方收到一个重复的ACK,则认为已经有一个数据包离开了网络,于是将拥塞窗口加1。

tcp的可靠机制
TCP协议作为一个可靠的面向流的传输协议,其可靠性和流量控制由滑动窗口协议保证,而拥塞控制则由控制窗口结合一系列的控制算法实现。
一、滑动窗口协议
关于这部分自己不晓得怎么叙述才好,因为理解的部分更多,下面就用自己的理解来介绍下TCP的精髓:滑动窗口协议。
所谓滑动窗口协议,自己理解有两点:1. “窗口”对应的是一段可以被发送者发送的字节序列,其连续的范围称之为“窗口”;2. “滑动”则是指这段“允许发送的范围”是可以随着发送的过程而变化的,方式就是按顺序“滑动”。在引入一个例子来说这个协议之前,我觉得很有必要先了解以下前提:
-1. TCP协议的两端分别为发送者A和接收者B,由于是全双工协议,因此A和B应该分别维护着一个独立的发送缓冲区和接收缓冲区,由于对等性(A发B收和B发A收),我们以A发送B接收的情况作为例子;
-2. 发送窗口是发送缓存中的一部分,是可以被TCP协议发送的那部分,其实应用层需要发送的所有数据都被放进了发送者的发送缓冲区;
-3. 发送窗口中相关的有四个概念:已发送并收到确认的数据(不再发送窗口和发送缓冲区之内)、已发送但未收到确认的数据(位于发送窗口之中)、允许发送但尚未发送的数据以及发送窗口外发送缓冲区内暂时不允许发送的数据;
-4. 每次成功发送数据之后,发送窗口就会在发送缓冲区中按顺序移动,将新的数据包含到窗口中准备发送;
TCP建立连接的初始,B会告诉A自己的接收窗口大小,比如为‘20’:
字节31-50为发送窗口

 A发送11个字节后,发送窗口位置不变,B接收到了乱序的数据分组:

 只有当A成功发送了数据,即发送的数据得到了B的确认之后,才会移动滑动窗口离开已发送的数据;同时B则确认连续的数据分组,对于乱序的分组则先接收下来,避免网络重复传递:

二、流量控制
流量控制方面主要有两个要点需要掌握。一是TCP利用滑动窗口实现流量控制的机制;二是如何考虑流量控制中的传输效率。

  1. 流量控制
    所谓流量控制,主要是接收方传递信息给发送方,使其不要发送数据太快,是一种端到端的控制。主要的方式就是返回的ACK中会包含自己的接收窗口的大小,并且利用大小来控制发送方的数据发送:

    这里面涉及到一种情况,如果B已经告诉A自己的缓冲区已满,于是A停止发送数据;等待一段时间后,B的缓冲区出现了富余,于是给b发送报文告诉A我的rwnd大小为400,但是这个报文不幸丢失了,于是就出现A等待B的通知||B等待A发送数据的死锁状态。为了处理这种问题,TCP引入了持续计时器(Persistence timer),当A收到对方的零窗口通知时,就启用该计时器,时间到则发送一个1字节的探测报文,对方会在此时回应自身的接收窗口大小,如果结果仍未0,则重设持续计时器,继续等待。

  2. 传递效率
    一个显而易见的问题是:单个发送字节单个确认,和窗口有一个空余即通知发送方发送一个字节,无疑增加了网络中的许多不必要的报文(请想想为了一个字节数据而添加的40字节头部吧!),所以我们的原则是尽可能一次多发送几个字节,或者窗口空余较多的时候通知发送方一次发送多个字节。对于前者我们广泛使用Nagle算法,即:
    *1. 若发送应用进程要把发送的数据逐个字节地送到TCP的发送缓存,则发送方就把第一个数据字节先发送出去,把后面的字节先缓存起来;
    *2. 当发送方收到第一个字节的确认后(也得到了网络情况和对方的接收窗口大小),再把缓冲区的剩余字节组成合适大小的报文发送出去;
    *3. 当到达的数据已达到发送窗口大小的一半或以达到报文段的最大长度时,就立即发送一个报文段;
    对于后者我们往往的做法是让接收方等待一段时间,或者接收方获得足够的空间容纳一个报文段或者等到接受缓存有一半空闲的时候,再通知发送方发送数据。
    TCP协议作为一个可靠的面向流的传输协议,其可靠性和流量控制由滑动窗口协议保证,而拥塞控制则由控制窗口结合一系列的控制算法实现。

猜你喜欢

转载自blog.csdn.net/weixin_43700671/article/details/88949718