【计算机网络】流量控制、拥塞控制、三次握手、四次挥手
一、流量控制
流量控制是让发送方的发送速率不要太快,让接收方来得及接收。利用滑动窗口机制实现TCP连接上对发送方的流量控制。
TCP采用大小可变的滑动窗口进行流量控制,窗口大小的单位是字节。
发送端收到了对方对前 400 字节数据的确认,但对方通知发送端必须把窗口减小到 400 字节。现在发送端最多还可发送 400 字节的数据。
二、拥塞避免
2.1 慢开始和拥塞避免
三、三次握手和四次挥手
TCP在传输之前会进行三次沟通,一般称为“三次握手”,传完数据断开的时候要进行四次沟通,一般称为“四次挥手”。
两个序号和三个标志位:
(1)序号:seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。
(2)确认序号:ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,ack=seq+1。
(3)标志位:共6个,即URG、ACK、PSH、RST、SYN、FIN等,具体含义如下:
(A)URG:紧急指针(urgent pointer)有效。
(B)ACK:确认序号有效。
(C)PSH:接收方应该尽快将这个报文交给应用层。
(D)RST:重置连接。
(E)SYN:发起一个新连接。
(F)FIN:释放一个连接。
需要注意的是:
(A)不要将确认序号ack与标志位中的ACK搞混了。
(B)确认方ack=发起方req+1,两端配对。
(1)在第一次消息发送中,A随机选取一个序列号x作为自己的初始序号发送给B,同时SYN标志位为1代表发起连接;
(2)第二次消息B使用ACK=1对A的数据包进行确认,因为已经收到了序列号为x的数据包,准备接收序列号为x+1的包,所以ack=x+1,同时B告诉A自己的初始序列号,就是seq=y;
(3)第三条消息A告诉B收到了B的确认消息并准备建立连接,A自己此条消息的序列号是x+1,所以seq=x+1,而ack=y+1是表示A正准备接收B序列号为y+1的数据包。
四次挥手:
由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,
收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。
首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭,上图描述的即是如此。
(1)客户端首先发送连接释放报文,这个报文首部FIN=1,序列号seq=u(等于前面传过来的数据最后一个字节的序号+1),此时客户端进入FIN-WAIT-1状态,等待服务器确认。TCP规定,FIN报文段即使不带数据,也要消耗一个序号。
(2)服务器收到释放报文段后发出确认,确认号ack=u+1,这个报文段自己的序号是v(等于服务器传送的数据最后一个字节的序号+1),此时服务器进入CLOSE-WAIT状态,此时处于半关闭状态,即客户端已经不发送数据了,但服务器要发送数据,客户端也得接收。(时长是CLOSE-WAIT的长度)
(3)客户端接收到服务器的确认后,进入FIN-WAIT-2状态,等待服务器发送连接释放报文。
(4)服务器如果没有要发送的数据,就可以发送连接释放报文,FIN=1,假定序号为w(因为在半关闭状态服务器可能会发送数据),服务器要重复上次收到的确认序号ack=u+1,此时服务器进入LAST-ACK状态。
(5)客户端收到服务器发来的连接释放报文,在报文中将ACK=1表示收到确认,确认号ack=w+1表示是对序号为w的确认,自己的序号是seq=u+1,此时客户端进入TIME-WAIT状态。但是此时TCP连接还没有释放,必须经过2MSL(最长报文段寿命的两倍)后,客户端撤销相应的TCB之后,才进入CLOSED状态。
(6)服务器收到了客户端的确认之后,立即进入CLOSED状态。撤销了TCB之后,TCP连接就结束了。
为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
第一,保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,
站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,
应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,
而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。
第二,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。
客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。
这样新的连接中不会出现旧连接的请求报文。
为什么建立连接是三次握手,关闭连接确是四次挥手呢?
建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。
而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。