tcp--握手

状态

LISTEN:监听TCP端口的链接请求服务器

SYN-SENT:客户端在发送SYN后等待对方确认cookie

SYN-RECEIVED:服务端在收到SYN后,发送一个SYN,ACK等待对方确认网络

ESTABLISHED:表明一个打开的链接,双方正在传输数据socket

FIN-WAIT-1:主动发送FIN中断请求方处于的状态tcp

FIN-WAIT-2:主动发送方接收到FIN确认ACK后处于的状态code

CLOSE-WAIT:被动关闭方接收到FIN回复ACK确认后处于的状态队列

CLOSING:等待远程TCP对链接中断的确认图片

LAST-ACK:被动关闭方在接受到FIN并回复ACK确认,在一段时间后在给主动方发送FINip

TIME-WAIT:主动发送方接收到FIN回复ACK确认后,处于的状态,该状态持续2个MSL(Max Segment Lifetime)资源

CLOSED:被动关闭方接受到ACK确认后,关闭套接字

盗图一张

创建链接的三次握手

客户端发送一个带SYN(syn=j)包到服务端,客户端状态closed->syn_send

服务端接收到SYN包,必须确认客户端的SYN(ack=j+1),同时也发送一个SYN包(syn=k),即SYN+ACK包,服务状态listen->syn_recevied

客户端接受到SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端syn_send->establish;服务端接收到确认包后syn_recevied->establish

关闭链接的四次握手

客户端发送一个FIN(fin=m)包,关闭客户端到服务端的数据传输,客户端establish->fin_wait1

服务端接受到FIN包,回复一个ACK(ack=m+1),服务端establish->close_wait

客户端接受到FIN的确认包后,客户端fin_wait1->fin_wait2

当服务端接收到来自客户端的FIN后,并不会当即调用close,而是在一段时后再调用close,这回给客户端发送一个FIN(fin=n)包,服务端close_wait->last_ack

客户端接受到服务端的FIN后,向服务回复一个ACK(ack=n+1),客户端fin_wait2->time_wait,服务端在接收到ACK回复后,服务端las_ack->close

完整的状态转移过程

客户端: closed -> syn_send -> establish -> fin_wait1 ->fin_wait2 -> TIME-WAIT -> closed

服务端: listen -> syn_recevied -> establish -> close_wait -> last_ack -> closed

主动关闭方才会处于time_wait,在2个MSL后才会closed,一般状况下是分钟级别,若是系统参数设置不合理,会有了大量的处于time_wait的socket占用资源

当发现有大量的tme_wait时能够经过调整内核参数来解决

编辑文件/etc/sysctl.conf,加入如下内容:

net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30

而后执行 /sbin/sysctl -p 让参数生效。 net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少许SYN攻击,默认为0,表示关闭; net.ipv4.tcp_tw_reuse = 1 表示开启重用。容许将TIME-WAIT sockets从新用于新的TCP链接,默认为0,表示关闭; net.ipv4.tcp_tw_recycle = 1 表示开启TCP链接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。 net.ipv4.tcp_fin_timeout 修改系默认的 TIMEOUT 时间

为何是这样呢

为何创建三次而关闭四次呢?当服务端接受到SYN是,通常都是同时回复SYN和ACK两个包,但因为TCP是全双工的工做,在一个方收到FIN时仅仅表示对方没有数据传输了,但并不表明本身的数据也都发送完毕了,因此在收到FIN时会当即时候一个ACK,在本身数据传输完毕后再发送一个FIN。

为何TIME_WAIT要等2MSL?由于种种缘由没法确保最有个ACK会被接受到,因此主动关闭方须要维持一个状态。被动关闭方在LAST_ACK一段时间内,若是没有收到确认,会再次重发,主动关闭处于time_wait时仍能够对该ACK作出确认。若是客户端直接由fin_wait2->closed,因为网络信号很差,那么服务端可能会一直处于last_ack状态,像这种状况通常都会利用心跳包机制来检测。

相关文章
相关标签/搜索