tcp一端断开,另一端还是established 状态

遇到一个奇怪的问题:当服务端处理不过来的时候,把客户端kill 掉,使用netstat 查看,还有established 状态的tcp 连接;

原因:由于服务器处理不过来,导致tcp 缓冲区堆积,FIN的数据包不是丢了就是还未被处理,netstat 信息如下:

tcp 129 0 0.0.0.0:15613 0.0.0.0:* LISTEN 37407/AAAAA

tcp 5346128 0 127.0.0.1:15613 127.0.0.1:56210 ESTABLISHED 37407/AAAAA

tcp 567364 0 127.0.0.1:15613 127.0.0.1:54450 ESTABLISHED 37407/AAAAA

tcp 5314874 0 127.0.0.1:15613 127.0.0.1:55764 ESTABLISHED 37407/AAAAA

在定位的过程中,纠正了自己之前的一个误解;

1,socket 默认是不打开keepalive 的,如果想打开需要执行:

int keepAlive = 1;    // 非0值,开启keepalive属性
       setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));

int keepIdle = 60;    // 如该连接在60秒内没有任何数据往来,则进行此TCP层的探测

int keepInterval = 5; // 探测发包间隔为5秒

int keepCount = 3;        // 尝试探测的最多次数

setsockopt(sockfd, SOL_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle));

setsockopt(sockfd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));

setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount) ;

另外,tcp keepalive 的相关配置如下:

 sudo sysctl -a | grep keepalive

net.ipv4.tcp_keepalive_time = 7200

net.ipv4.tcp_keepalive_probes = 9

net.ipv4.tcp_keepalive_intvl = 75

2,有数据时,重试的时间配置项:

root@localhost data0]# sysctl -a | grep tcp_retries
       net.ipv4.tcp_retries1 = 3
       net.ipv4.tcp_retries2 = 15  // 15的单位是次数,大约960多秒

3,SS命令可以查看tcp 相关参数,例如,滑动窗口大小,timer 的类型等;

4,syn_queue  和  accept_queue 大小限制:

     如果要设置未完成连接的队列长度,可以设置 tcp_max_syn_backlog 这个参数。

     如果服务器收到大量的正常请求,导致服务器负载非常高,不要为了应对这种情况开启 tcp_syncookies

     文档里用了大写的 “MUST NOT” 来提醒我们,然后很良心地建议去修改 tcp_max_syn_backlogtcp_synack_retriestcp_abort_on_overflow

     系统发回给客户端 SYN/ACK 后,如果没收到客户端的 ACK,会重发 SYN/ACK,tcp_synack_retries 用于指定重发 SYN/ACK 的次数,默认是 5 次.

      max syn queue size =  用户传入的 10 向上取了最接近的 2 的指数幂值 16。//backlog, net.core.somaxconn, net.ipv4.tcp_max_syn_backlog  backlog 是listen 函数的参数

      参考:https://juejin.cn/post/6844904071367753736

     listen 函数的 backlog 等待应用程序 accept 的连接队列的长度,这个队列里是 ESTABLISHED 状态的连接,而不是还未完成三次握手的连接

      max accept queue: size = min(backlog, net.core.somaxconn) 

     注意,在4.3版本之前的内核,SYN队列的大小是用另一种方式计算。

      SYN队列的最大大小以前是用net.ipv4.tcp_max_syn_backlog来配置,但是现在已经不再使用了。

      现在用net.core.somaxconn来同时表示SYN队列和Accept队列的最大大小。

      

 

参考连接:

https://blog.csdn.net/lanyang123456/article/details/90578453

http://www.netkiller.cn/linux/system/network/network.check.html

https://fixatom.com/some-doubts-and-misunderstandings-of-tcp/

 

猜你喜欢

转载自blog.csdn.net/zgb40302/article/details/110818618