TCP原理解析

TCP协议通过三次握手建立连接,确保双方都能通信。在连接断开时,采用四次挥手确保数据完整传输。TCP的可靠性体现在校验和、序列号/确认应答、超时重传、最大消息长度和滑动窗口控制等方面。同时,TCP使用拥塞控制算法,如慢启动、拥塞避免、快重传和快恢复,来适应网络状况并避免数据丢失。

报文格式

序号:Seq(Sequence Number)序号占32位,用来标识从计算机A发送到计算机B的数据包的序号,计算机发送数据时对此进行标记。

. 确认号:Ack(Acknowledge Number)确认号占32位,客户端和服务器端都可以发送,Ack = Seq + 1。

. 标志位:每个标志位占用1Bit,共有6个,分别为 URG、ACK、PSH、RST、SYN、FIN,具体含义如下:

URG:紧急指针(urgent pointer)有效。

ACK:确认序号有效。

PSH:接收方应该尽快将这个报文交给应用层。

RST:重置连接。

SYN:建立一个新连接。

FIN:断开一个连接。

三次握手

1.客户端首先会生成一个随机数J作为数据包的序号,给服务端发送一个SYN包,包的序号seq设置为J,发送成功后,自己进入SYN_SENT 状态,代表发送SYN包成功,等待服务端的确认。

2.服务端收到SYN包之后,会进入到SYN_RECV状态,同时为了检测服务端到客户端是否通畅,会给客户端发送一个SYN包,将ACK设置为1,并且会带上ack=J+1,生成随机数作为包的序号,seq=K,用于确认之前收到了客户端发送的SYN包。

3.客户端收到服务端发送的SYN包后,会检测ACK标志位是否为1,并且ack是否等于J+1,如果是的话,就说明之前服务器收到了客户端发送的SYN包,并且服务端发送给客户端的SYN包也是可以收到的,所以需要给服务端发送ACK包,ACK=1,ack=K+1。

4.服务端收到ACK回应后,检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,客户端和服务器端进入ESTABLISHED状态,完成三次握手,随后客户端与服务器端之间可以开始传输数据了。

四次挥手

TCP是全双工的连接,断开每一方向的连接都需要发送断开请求,断开确认。所以总共需要发送4个包才能确定连接的断开。

1.首先客户端给服务端发送一个FIN包,seq=J,客户端进入FIN_WAIT_1状态,代表客户端已经没有数据发送给服务端了。

2.服务端接收到FIN包之后,会给客户端发送一个ACK,ack=J+1,用于确认客户端-服务端这边的连接进行断开。同时会进入到CLOSE_WAIT状态,表示在等待关闭,因为服务端往客户端可能还在继续传输数据,暂时还不能断开。客户收到服务端返回的ACK回应后,会进入到FIN_WAIT_2状态,代表客户端-服务端的连接已经断开成功,等待服务端发送FIN包断开服务端-客户端的连接。

3.服务端发现没有数据发给客户端后,会发一个FIN包给客户端,并且进入LAST_ACK,代表等待客户端的ACK,一旦收到ACK,代表连接正式断开,服务端可以进入CLOSE状态。

4.客户端收到服务端发送的FIN包后,说明连接已经断开了,但是需要服务端知道,客户端会给服务端发送一个ACK包通知服务端,并且会进入TIME_WATING状态,代表超过超时时间后自动进入CLOSE状态,如果ACK包中途丢了,服务端会再发送FIN包,客户端会进行ACK包重发,这也是TIME_WAITING状态的意义。

close_wait太多怎么处理?

close_wait 主要在TCP四次挥手时,服务端给客户端返回ACK应答后,由于自身还需要给客户端传输数据,所以会进入到close_wait状态,直到不需要给客户端发数据了,才会去给客户端发送FIN包,同时进入LAST_ACK状态。(被动关闭的一方没有及时发出 FIN 包就会导致自己一直处于close_wait状态。)

tcp_keepalive_time默认是2个小时,也就是TCP空闲连接可以存活2个小时,在close_wait状态下,可以把这个时间调小,减少处于close_wait连接的数量

time_wait太多是怎么造成的?

首先time_wait状态存在的意义是可以有效地终止TCP连接,因为主动关闭方发生ACK给被动关闭方后,需要等待2MSL的时间(MSL指的是报文最大有效存活时间,在linux下是60s),在这个时间内,如果没有收到被动关闭方重发的FIN包,就说明连接关闭完成了。 在高并发短连接的业务场景下,由于短连接的传输数据+业务处理的时间很短,所以服务器处理完请求就会立即主动关闭连接,并且进入TIME_WAITING状态,而端口处于有个0~65535的范围中,除去系统占用的,总的数量有限。所以持续的到达一定量的高并发短连接,会使服务器因端口资源不足而拒绝为一部分请求服务。 可以通过修改TCP的默认配置来改善这个问题。

TCP怎么保证可靠性的?

TCP主要提供了检验和、序列号/确认应答、超时重传、最大消息长度、滑动窗口控制等方法实现了可靠性传输。

校验和:主要是将数据切分成若干个16位的二进制串,将每个二进制串看成一个二进制数,对这些数进行相加等运算得到一个校验和,然后接收方收到数据会使用同样的算法来对数据计算校验和,如果结果和发送端发过来的校验和一样,那么就校验成功。主要是为了防止接收方收到的是已经损坏的数据。

序列号/确认应答,超时重传:对发送的每个数据包都有一个序号,服务端收到数据包会返回一个ACK进行确认,如果在超过超时时间后,客户端还是没有收到服务端返回的ACK确认,就会对数据包进行超时重传。并且超时时间是动态变化的,初始值会大于正常的报文发送到接收到ACK回应的时间,重传后还没有得到回应会调大重传时间,然后进行重传。 例如:在Linux中,超时以500ms为单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍。其规律为:如果重发一次仍得不到应答,就等待2500ms后再进行重传,如果仍然得不到应答就等待4500ms后重传,依次类推,以指数形式递增,重传次数累计到一定次数后,TCP认为网络或对端主机出现异常,就会强行关闭连接。

最大消息长度:在建立TCP连接的时候,双方约定一个最大的长度(MSS)作为发送的单位,重传的时候也是以这个单位来进行重传。理想的情况下是该长度的数据刚好不被网络层分块。

滑动窗口控制:就是发送方在发送一个包时,不需要等到收到接收方对上一个包的确认应答后,才能发。只需要当前发送的包在滑动窗口内就行了。发送方每接收到一个确认应答,就会向后移动一位。 对于接收方而言,只会给客户端返回当前需要的包的序号,也就是对目前已收到的包的确认应答。(在拥塞控制里面,一般判断是否是网络拥塞导致丢包,有两种机制,超时重传,超过重传时间,还没有收到回应,另一个是收到三个重复确认ACK,就是比如中间某个数据包N丢了,那么后面发送的3个数据包如果被服务端接收到了,返回的确认回答ACK=N,代表没有收到数据包N,需要发送方重传,重复确认ACK超过3个,就认为发送了网络拥塞)

流量控制是怎么实现的?

因为滑动窗口设置得太大或太小都不易于数据传输,所以是根据接收端的反馈,发送端可以对滑动窗口大小进行动态调整的。发送端在发送的数据包的序号必须小于最大的滑动窗口值,所以当发送的数据包过多,导致接收端的缓冲区写满时,接收端会通知给客户端将滑动窗口设置为更小的值,减少发送的量,达到一个流量控制的效果。

TCP的拥塞控制

拥塞:随着网络中的主机增加其发送速率并使网络变得十分拥挤,此时会经常发生丢包现象,导致网络的传输效率急剧降低。分组的超时重传通常被作为网络拥塞的标志。

如果不对网络拥塞进行控制,整个网络的吞吐量将随着输入负荷的增大而下降,降低网络的传输效率,如下图:

TCP的4种拥塞控制算法(慢开始、拥塞避免、快重传、快恢复)

为了便于讨论做一下假设

数据是单方向传送的,另一个方向只传输确认

接收方的总是有足够大的缓冲区,因此发送方的发送窗口仅由网络的拥塞程度决定,事实上发送窗口的大小由拥塞窗口和接收方的接收窗口大小共同控制,也即发送窗口 = min[接收窗口, 拥塞窗口];

以最大报文段MSS的个数作为讨论单位,而不是以字节为单位

发送方维护一个叫做拥塞窗口cwnd(congestion window)的状态变量,其值取决于网络的拥塞状况,动态变化

拥塞窗户的维护原则:只要网络没有出现拥塞,cwnd就增大一些;但只要网络出现拥塞,拥塞窗口就减小一些;以分组发生超时重传作为发生网络拥塞的依据

TCP还维护一个慢开始门限ssthresh状态变量

当cwnd < ssthresh时,使用慢开始算法

当cwnd > ssthresh时,使用拥塞避免算法

当cwnd = ssthresh时,既可以使用慢开始算法,也可以使用拥塞避免算法

当发生数据正常丢包,但又不是网络拥塞时,使用快重传算法和快恢复算法

如何判断是发生了正常丢包而不是网络拥塞呢?

当发送方连续接收到3次重复确认时,说明这网络不拥塞,只是正常丢包了

慢启动

传输轮次:指把发送窗口内可以发送的数据全部发送并接收到最后一个TCP报文的确认报文这样一个来回

通常在一条TCP连接开始时,cwnd被设置为1个MSS(最大报文段),也即cwnd=1

该阶段,每当TCP发送方将发送窗口的数据发送完,并顺利接收到所有的确认后,就会将拥塞窗口大小翻倍,也即慢启动阶段,cwnd以指数形式增长,如上图所示;注意这里忽略了接收窗口的影响,上文也提到了。

拥塞避免

拥塞窗口会一直增长直到到达慢开始门限ssthresh,开始执行拥塞避免算法,该阶段的拥塞窗口变为线性增长,每次cwnd+1,也即每次增加一个MSS

快重传

发送方一旦收到3个连续的重复确认,就将相应的报文段立即重传,而不是等待该报文的重传计时器超时再重传

快恢复

如果发送方收到了3个重复确认,就执行快恢复算法,将慢开始门限sstresh和拥塞窗口cwnd都设置为当前拥塞窗口的一半,然后执行拥塞避免算法

此时将更新ssthresh的值为当前拥塞窗口的一半,上图中是更新为24的一半即12

更新cwnd的值为1

然后继续执行慢启动—拥塞避免,如上图所示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值