tcp的三次握手
传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
其中比较重要的字段有:
(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,两端配对。
三次握手图解:
第一次握手:建立连接,客户端发送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故障了怎么办?
保活机制
向对方发送保活探测报文,如果问收到回应则继续发送。尝试次数达到保活探测次数任未收到相应则中断链接。
四次挥手图解:
第一次挥手: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链接,而服务端忙于读写,没有及时关闭连接。
需要检查代码,尤其是释放资源。