游戏卡顿白皮书 › L8 Socket 与协议
RST 强制关闭导致最后的数据丢失 SO_LINGER, abrupt RST
原因 ID sk-linger · 主责 研发团队·服务器开发
在含图示和实验的完整版中打开此卡片 →
服务器仓促断开连接时,最后发出的提示或存盘完成信号会丢失。
起因 服务器以强制关闭(RST)的方式关闭连接。SO_LINGER 设为 0 秒,或者没读完收到的数据就关闭,都会这样 → 结果 还在发送中的踢人原因和最后的数据被丢弃 → 画面表现 莫名其妙地出现“因未知错误断开连接”
- 症状
- 掉线
- 因素
- 丢包
- 谁会遇到
- 只有我
- 何时出现
- 偶尔随机
- 负责方
- 主责 研发团队·服务器开发
- 研发团队要做的事
- 发送原因后先只关闭发送方向(shutdown),把收到的数据一直读到对方关闭,然后再关闭;避免 SO_LINGER 0 秒。
- 监控图上
- 偶发随机尖峰 · 以 RST 结束的连接数
- 查看位置
- 看 nstat -az 中 TcpExtTCPAbortOnData(还有待发数据时以 RST 关闭,SO_LINGER 0 秒)、TcpExtTCPAbortOnClose(还有未读数据时关闭)的增量,在断开瞬间的服务器侧抓包中看发出的是 FIN 还是 RST
- 确认依据
- “因未知错误断开连接”的反馈时间点上服务器发出了 RST,AbortOnData、AbortOnClose 增加
- 排除依据
- 服务器以 FIN 正常关闭却看不到原因,看客户端的关闭处理
- 确认手段
- 运维工具即可确认(无需游戏代码)
出处
- closesocket function (winsock.h) Microsoft
开启 SO_LINGER 并把时间设为 0,会变成立即重置连接的强制关闭,没发出去的数据会丢失 - RFC 9293: Transmission Control Protocol (TCP) IETF
还有收到的数据没读就关闭时,会发送 RST 告知数据丢失 - Graceful Shutdown, Linger Options, and Socket Closure Microsoft
先用 shutdown 只关闭发送,收到对方的关闭通知后再关闭 socket 的顺序 - SNMP counter Linux kernel
TcpExtTCPAbortOnData:因 SO_LINGER 0 秒等原因,还有待发数据时以 RST 关闭;TcpExtTCPAbortOnClose:还有未读数据时关闭而发送 RST
相关原因
同一层:L8 Socket 与协议
其他层中同样导致“掉线”的原因
查看含图示和实验的原卡片