tcp的三次握手

传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。

tcp的三次握手

其中比较重要的字段有:

(1)序号(sequence number):Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。

(2)确认号(acknowledgement number):Ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,Ack=Seq+1。

(3)标志位(Flags):共6个,即URG、ACK、PSH、RST、SYN、FIN等。具体含义如下:

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

ACK:确认序号有效。PSH:接收方应该尽快将这个报文交给应用层。

RST:重置连接。SYN:发起一个新连接。

FIN:释放一个连接。

需要注意的是:

不要将确认序号Ack与标志位中的ACK搞混了。确认方Ack=发起方Seq+1,两端配对。

三次握手图解:

tcp的三次握手

第一次握手:建立连接,客户端发送syn=1到服务端,并进入SYN_SENT状态,等待服务器确认。

第二次握手:服务器接收到SYN包,必须确认客户端的SYN(ack=x+1).同时也发送一个SYN+ACK包,并进入SYN_RCVD状态。

第三次握手:客户端收到服务器的SYN+ACK包后,想服务器发送一个ACK(ack=y+1)包,此时包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

问题一:为什么需要三次握手才能建立起链接?

为了初始化seq num的值,也就是图中的x,y值,保证应用层接收到的数据不会因为网络传输问题而乱序

问题二:首次握手时,SYN超时?

第三次握手,服务端没有收到客户端的ack确认。服务端就会不断重试直至超时,重试时间从1s开始每次翻倍。linux默认63s才断开连接。可能会导致服务器遭到恶意攻击(只建立第一次握手然后下线)。

SYN队列满了以后,通过tcp_syncookies参数回发SYN Cookie

若为正常连接则client会回发SYN Cokkie,直接建立连接。即使SYN队列满了也能建立链接

问题三:建立连接后Client故障了怎么办?

保活机制

向对方发送保活探测报文,如果问收到回应则继续发送。尝试次数达到保活探测次数任未收到相应则中断链接。

四次挥手图解:

tcp的三次握手

第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据连接,Client进入FIN_WAIT1状态。

第二次回收:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(u+1),Server进入Close_Wait状态

第三次挥手:Server发送一个FIN用来关闭server与client的数据传输,Server进入LAST_ACK状态

第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1(w+1),Server进入Closed状态,Client也会在等待2MSL后,进入Closed状态。完成四次挥手。

问题一:为什么有个TIME_WAIT状态?

确保有足够的时间让对方收到ACK包,如果没有收到,被动关闭的那端就会重发FIN包,一来一回就是2MSL。

问题二:为什么需要四次挥手才能断开链接?

tcp是全双工(双方可以同时发送数据)发送方和接收方都需要FIN报文和ACK报文。即双方各自要中断和确认一次。

问题三:服务求出现大量的CLOSE_WAIT状态

客户端一直请求服务端,返回异常信息。但是服务端却没有收到请求。

原因:对方关闭socket链接,而服务端忙于读写,没有及时关闭连接。

需要检查代码,尤其是释放资源。