【网络】TCP协议形象讲解

1 TCP简介

TCP协议全称: 传输控制协议, 顾名思义, 就是要对数据的传输进行一定的控制。该协议处于7层协议中的传输层。TCP协议报文如图1.1所示【网络】TCP协议形象讲解_第1张图片在上述图中,有几个英文单词,分别表示的意思如下(摘自《计算机网络安全教程》):

  • URG:是否使用紧急指针。0为不使用,1为使用。
  • ACK:请求-应答状态。0为请求,1为应答。
  • PSH:以最快的速度传输数据。
  • RST:连接复位,首先断开连接然后重建。
  • SYN:同步连接序号,用来建立连接。
  • FIN:结束标志。0表示结束连接请求,1表示结束连接。
  • ack:表示下一个数据包的编号
  • seq:表示当前数据包的编号

2 TCP三次握手

TCP三次握手过程如下图2.1所示:【网络】TCP协议形象讲解_第2张图片 

  • 第一次握手:客户端向服务端发送连接请求,SYN=1,seq=x(客户端当前发送的数据包编号为x),ACK=0(请求)。此时客户端进入SYN-SENT(同步已发送)状态。
  • 第二次握手:服务器收到请求报文后,同意建立连接,则发回确认包,确认包中包含SYN=1,ACK=1(应答),seq=y(服务端当前发送的数据包编号为y),ack=x+1(客户端下一次应该发送的数据包编号为x+1,如果不是,则服务端会丢弃该数据包)。此时服务端进入SYN-RCVD(同步收到)状态。
  • 第三次握手:客户端接收到确认包后,给服务端发送ACK=1(应答,表示已经接收到)。此时客户端和服务端都进入ESTABLISHED(已建立连接)状态。

总结:三次挥手可以形象地表示为:A向B请求(ACK=0)连接,B如果同意连接则回答(ACK=1)A说同意连接,A接收到B的信息后也回答(ACK=1)道:我接收到你的同意回复了。这样三次握手完成。

3 TCP四次挥手过程

四次挥手过程如下图3.1所示【网络】TCP协议形象讲解_第3张图片 

  • 客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
  • 服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
  • 客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
  • 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w(是w而不是v+1,是因为在发送了编号为v的数据后,可能还发送了其它数据),此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
  • 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
  • 服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

总结:
四次挥手过程可以简短形象的用以下文字来表述:

  • A想要断开连接,因此向B发送了断开连接请求,然后A进入等待1状态;
  • B接收到请求后就发送消息询问A是否确定断开连接,然后B就进入关闭等待状态;
  • A接收到询问消息后就进入等待2状态,等待B发送最后的数据;B此时不等A发送最终的确认消息,而是将未发送完的数据发送给A,并向A发送结束连接报文,发送完后B就进入最终确认状态;
  • A接收到最后的数据后,就发送最终确认关闭连接的消息,然后自己进入时间等待状态;B接收到最终确认后就断开了TCP连接;A等待一段时间后也自己断开了TCP连接。

4 常见面试问题

  • 【问题1】为什么连接的时候是三次握手,关闭的时候是四次握手?

因为连接时只需要最少三次握手就能确定服务端和客户端是否建立连接;而关闭时,当客户端请求断开连接时,服务端接收到断开连接请求时,可能还有数据未传输完,因此不能立即断开连接,而是给客户端发送确认报文,表示你的请求我已经收到了,等待数据传输完成后再给客户端发送断开连接报文,然后客户端发送最终确认消息,所以关闭时是四次握手。

  • 【问题2】如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

  • 【问题3】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可能最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在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连接。

  • 【问题4】为什么是3次握手而不是两次?

因为两次握手会出现很多问题。两次握手可能有以下几种情况:

  • 可能发生死锁的情况。客户端发送了请求连接的数据包,服务端收到后也向客户端发送一个应答数据包。假设只进行两次握手,那么此时服务端就认为连接已经建立,因此就会向客户端发送数据。但此时可能客户端没有收到服务端的应答信息,那么客户端就认为连接没有建立成功,就会一直等待服务端发送应答数据,并且无视服务端发送的其它数据包(因为客户端没有收到服务端发送的应答数据包,所以也不知道客户端定义的数据包序号是多少,也就不能对数据进行检验等工作,所以它一定会等待服务端发送应答数据包)。而服务端因为客户端没有接收到数据就会进行数据重传等,所以就会陷入了死循环。
  • 断开的服务重新连接并发送数据的情况。客户端发送一个请求建立连接的数据包,由于网络的不稳定等因素,可能导致这个数据包拥塞堵塞,到达一定时间后(可以叫它应答超时),客户端没有收到服务端的信息就会再次重传请求建立连接的数据包。假设此时服务端收到了请求信息,那么此时服务端会向客户端发送一个应答数据,因为两次握手,所以服务端认为此时已经建立起了连接。假设此时一切正常,并且完成了数据的传输,然后也断开了连接。而此时,之前由于网络问题导致堵塞的请求数据包到达了服务端,服务端认为又有新的客户端请求建立连接,因此接收到数据后向客户端发送应答数据包,并认为已经建立了连接,就会向客户端发送数据包。而此时因为客户端已经关闭,就会无视服务端发送的数据,导致资源浪费。

你可能感兴趣的:(笔记)