1,tcp三次握手
TCP A TCP B
1. CLOSED LISTEN
2. SYN-SENT --> <SEQ=100><CTL=SYN> --> SYN-RECEIVED
3. ESTABLISHED <-- <SEQ=300><ACK=101><CTL=SYN,ACK> <-- SYN-RECEIVED
4. ESTABLISHED --> <SEQ=101><ACK=301><CTL=ACK> --> ESTABLISHED
2,tcp四次挥手
TCP A TCP B
1. ESTABLISHED ESTABLISHED
2. (Close)
FIN-WAIT-1 --> <SEQ=100><ACK=300><CTL=FIN,ACK> --> CLOSE-WAIT
3. FIN-WAIT-2 <-- <SEQ=300><ACK=101><CTL=ACK> <-- CLOSE-WAIT
4. (Close)
TIME-WAIT <-- <SEQ=300><ACK=101><CTL=FIN,ACK> <-- LAST-ACK
5. TIME-WAIT --> <SEQ=101><ACK=301><CTL=ACK> --> CLOSED
6. (2 MSL)
CLOSED
3,time-wait产生的原理及解决方案
3.1 time-wai产生原因
可以从四次挥手中看到,当A接收到B的FIN之后,A就把状态置为TIME-WAIT状态,直到等待2MSL时间之后,才变成CLOSED状态。
3.2 time-wait保持2MSL原因
MSL 是Maximum Segment Lifetime英文的缩写,中文可以译为“报文最大生存时间”,一般比ip头部里面的ttl还要大
原因一:若B最后没有接收到ack,则B会重发FIN包,这是A若为closed状态则会响应RST包,这时关闭连接就会异常,代码里面会抛出错误异常。若等待2msl则,A还是time-wait状态会响应B重发的FIN包,再次发送关闭ACK给B,B接收到ack之后,正常关闭连接。
原因二:关闭一个连接后,立马启动相同的ip和端口的连接,若此时原来的连接在网络上还有滞留的数据包,现在到达的话,则会错误的重组在新的连接上,导致异常,所以等待2msl时间,则是让这些滞留的数据包完全消失后,新的连接才可以启动。为啥要2,原因还是最后一个ack若B没有收到,会重发FIN包,这样时间就是:等待重发时间+1msl,所以最少需要2个msl时间。
3.3 time-wait解决
因为有2MSL等待时间,所以出现较多的time-wait可以算是正常现象,
对服务器来说,有大量的time-wait出现,表明服务端出现了大量断开连接的操作,可以适当增加超时断连的时间,让客户的断开连接。
服务端处理过多的time-wait也可以通过设置系统配置,使得time-wait占用的句柄资源可以快速重用及回收。配置调整如下:
1)打开/etc/sysctl.conf文件;
2)修改配置
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 时间
3)若还需要优化则可以更改以下配置
net.ipv4.tcp_max_syn_backlog =8192 表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
net.ipv4.tcp_max_tw_buckets =5000 表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。
4)最后执行/sbin/sysctl -p命令,让配置生效。
4,close-wait产生原因及解决方案
4.1 产生原因
从tcp的四次挥手可以看出,B接收到A的断开连接请求之后,B的状态就置为CLOSE-WAIT状态,直到B发送数据完成,并发送FIN标志给A的时候,此时才会更新状态为LAST-ACK。
4.2 解决方案
若服务端,有大量的套接字出现CLOSE-WAIT状态,说明服务有异常。
原因一:当接收到关闭套接字消息的时候,未关闭本地套接字。所以需要检查代码,关闭收到断开连接的tcp请求的套接字。
原因二:B所在的服务端,响应太慢,导致接收到A的断开连接请求后,没有时间处理该操作,或者是忙于其业务的处理,此时需要扩容,或者是调整api为异步操作尽快返回,或者是优化api处理逻辑。
5,tcp的拥塞控制
5.1 慢启动
连接开始,cwnd=1开始,成倍数增加,直到大于等于门限制ssthresh,开始启动拥塞避免算法。
5.2 拥塞避免
开始cwnd=cwnd+1的线性增长,若出现超时或者是丢包问题,使接收到3个及以上的相同ack,则会启动快速重传
5.3 快速重传
重传超时或者是丢包的包,随后进入快速恢复阶段
5.4 快速恢复
设置ssthresh=cwnd/2, cwnd=ssthresh+3,当接收到新数据的ack包,则启动拥塞避免算法
6,tcp为何会粘包
6.1 因为tcp是面向连接的、可靠的、基于字节流的协议,其中基于字节流特性,说明数据是流式到达应用层,需要应用层去保证数据包的完整性, 可以在应用层制定一套协议,用来切包。
网友评论