为什么用Workerman做游戏后端需要配置TCP的Keep-Alive?

夜婷姑娘_1031

夜婷姑娘_1031

2026-05-22

341人浏览

原创

workerman默认不启用tcp keep-alive,需在onconnect中用socket_set_option显式配置so_keepalive及tcp_keepidle、tcp_keepintvl、tcp_keepcnt参数,否则nat/防火墙易导致连接假死;应用层心跳与tcp保活须协同使用。

为什么用workerman做游戏后端需要配置tcp的keep-alive?

Workerman本身不自动启用TCP层Keep-Alive,游戏客户端常因NAT/防火墙静默断连,不配就容易出现“连接还活着但发不出包”的假死状态。

Workerman默认不开启TCP Keep-Alive

Workerman的TcpConnection对象在建立后,底层socket默认继承系统全局设置(Linux通常为2小时才探测),远超游戏场景容忍范围。它不会自动调用setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)),更不会调整TCP_KEEPIDLE、TCP_KEEPINTVL、TCP_KEEPCNT这三个关键参数。

这意味着:即使你设置了$connection->keepalive = true(这是Workerman应用层长连接开关,仅影响是否主动关闭空闲连接),TCP协议栈仍按系统默认策略保活——对游戏来说太迟钝、太不可控。

  • $connection->keepalive = true只是让Workerman不主动关掉空闲连接,和TCP保活机制无关
  • 真正起作用的是操作系统级socket选项,必须显式配置
  • Workerman未封装跨平台的Keep-Alive参数设置接口,需手动stream_set_option()或socket_set_option()

游戏场景下NAT和防火墙是主要断连元凶

移动端或家庭宽带环境中的NAT设备(如家用路由器)、运营商级NAT、企业防火墙,普遍会在60–300秒内清理“无数据交互”的TCP连接。它们只看IP+端口五元组是否有报文流动,不理解HTTP头或自定义心跳包语义。

此时TCP Keep-Alive探测包(空ACK)是唯一能穿透这些中间件并维持连接映射表的合法流量。

TextCortex
TextCortex

一款集AI写作、改写和知识辅助于一体的内容创作工具,可帮助用户快速完成多种类型的文本撰写与编辑任务。

下载
  • 客户端发完一个技能包后静默120秒 → NAT已删映射 → 下次发移动包被丢弃,但send()仍返回成功(因为内核缓冲区没满)
  • 服务器收不到后续数据,也收不到FIN/RST,连接卡在ESTABLISHED状态,变成“半开”
  • 只有TCP Keep-Alive在TCP_KEEPIDLE(如45秒)后开始探测,才能在NAT超时前触发重置或确认

如何在Workerman中正确配置TCP Keep-Alive

必须在onConnect回调里对原始socket资源操作,不能只依赖Workerman的keepalive属性。

示例(Linux环境,使用socket_set_option):

use Workerman\Worker;
use Workerman\Connection\TcpConnection;

$worker = new Worker('tcp://0.0.0.0:2345');

$worker->onConnect = function (TcpConnection $connection) {
    // 获取底层socket资源
    $socket = $connection->getSocket();
    if ($socket !== null && is_resource($socket)) {
        // 启用TCP Keep-Alive
        socket_set_option($socket, SOL_SOCKET, SO_KEEPALIVE, 1);
        // 首次探测延迟:45秒(避免刚连上就发包)
        socket_set_option($socket, IPPROTO_TCP, TCP_KEEPIDLE, 45);
        // 探测间隔:10秒
        socket_set_option($socket, IPPROTO_TCP, TCP_KEEPINTVL, 10);
        // 最大失败次数:3次(即30秒无响应后断连)
        socket_set_option($socket, IPPROTO_TCP, TCP_KEEPCNT, 3);
    }
};
  • Windows不支持TCP_KEEPIDLE/TCP_KEEPINTVL/TCP_KEEPCNT,只能设SO_KEEPALIVE,依赖系统默认(通常2小时)
  • PHP stream_set_option()在部分版本中对Keep-Alive参数支持不稳定,优先用socket_set_option()
  • 务必在onConnect里做,不能在onMessage或定时器里补 —— socket资源可能已失效

Keep-Alive和应用层心跳不是二选一,而是分层协作

TCP Keep-Alive解决“物理链路是否断开”,应用层心跳解决“对端进程是否存活+业务逻辑是否就绪”。游戏后端必须两者共存。

  • TCP Keep-Alive防止NAT撕毁连接,但它不保证你的PHP进程还在处理逻辑(比如进程OOM被kill,但TCP连接未关闭)
  • 应用层心跳(如每30秒{"type":"ping"})能触发onMessage,更新$connection->lastMessageTime,配合定时器清理僵死连接
  • 若只靠TCP Keep-Alive,服务端无法感知客户端逻辑崩溃;若只靠心跳,NAT早把连接回收了,心跳包根本发不出去

最容易被忽略的是:TCP Keep-Alive参数必须匹配你的网络部署环境。云服务器(如AWS/Azure)的负载均衡器、K8s Service、Ingress Controller都有各自空闲超时设置,它们往往比NAT更激进。比如Azure Load Balancer默认空闲超时是4分钟,那你的TCP_KEEPIDLE就得设成≤200秒,否则探测永远赶不上LB断连。

相关文章

在线游戏
在线游戏

海量精品小游戏合集,无需安装即点即玩,休闲益智、动作闯关应有尽有,秒开即玩,轻松解压,快乐停不下来

下载

相关标签:

workerman keep-alive

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
python是前端还是后端
python是前端还是后端

Python属于前端也属于后端,其灵活性和丰富的生态系统使得开发人员能够在不同的领域中灵活运用。本专题为大家提供python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

2263

5

前端和后端的区别
前端和后端的区别

前端关注的是用户界面的设计和交互,而后端则注重数据处理和逻辑控制。想了解更多前端后端的相关内容,可以阅读本专题下面的文章。

2024.03.19

5970

13

后端的主要工作内容介绍
后端的主要工作内容介绍

后端是应用程序的服务端部分,负责核心任务,如数据库交互、业务逻辑处理和响应客户端请求。想了解更多后端的相关内容,可以阅读本专题下面的文章。

2024.03.19

5286

10

C语言变量命名
C语言变量命名

c语言变量名规则是:1、变量名以英文字母开头;2、变量名中的字母是区分大小写的;3、变量名不能是关键字;4、变量名中不能包含空格、标点符号和类型说明符。php中文网还提供c语言变量的相关下载、相关课程等内容,供大家免费下载使用。

2023.06.20

2849

3

c语言入门自学零基础
c语言入门自学零基础

C语言是当代人学习及生活中的必备基础知识,应用十分广泛,本专题为大家c语言入门自学零基础的相关文章,以及相关课程,感兴趣的朋友千万不要错过了。

2023.07.25

2188

9

c语言运算符的优先级顺序
c语言运算符的优先级顺序

c语言运算符的优先级顺序是括号运算符 > 一元运算符 > 算术运算符 > 移位运算符 > 关系运算符 > 位运算符 > 逻辑运算符 > 赋值运算符 > 逗号运算符。本专题为大家提供c语言运算符相关的各种文章、以及下载和课程。

2023.08.02

1160

5

c语言数据结构
c语言数据结构

数据结构是指将数据按照一定的方式组织和存储的方法。它是计算机科学中的重要概念,用来描述和解决实际问题中的数据组织和处理问题。数据结构可以分为线性结构和非线性结构。线性结构包括数组、链表、堆栈和队列等,而非线性结构包括树和图等。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.09

1098

4

c语言random函数用法
c语言random函数用法

c语言random函数用法:1、random.random,随机生成(0,1)之间的浮点数;2、random.randint,随机生成在范围之内的整数,两个参数分别表示上限和下限;3、random.randrange,在指定范围内,按指定基数递增的集合中获得一个随机数;4、random.choice,从序列中随机抽选一个数;5、random.shuffle,随机排序。

2023.09.05

1296

5

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

2023.09.20

2038

7

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程