AsyncTcpConnection 连不上常见原因包括DNS解析失败、防火墙拦截、远端未监听端口;需用onConnect/onError捕获错误,手动处理超时与重连,提前解析域名,注意协议分帧与连接生命周期管理。

AsyncTcpConnection 连不上目标服务的常见原因
Workerman 的 AsyncTcpConnection 不是“发个请求就完事”的工具,它默认不自动重连、不自动处理超时、也不校验连接是否真正建立成功。很多连不上,其实是卡在 DNS 解析失败、防火墙拦截、或远端服务未监听对应端口,但代码里没暴露错误。
- 用
$connection->onConnect而不是靠new AsyncTcpConnection的返回值判断是否连上——构造函数只创建对象,不触发实际连接 - 必须手动设置
$connection->onError,否则 DNS 失败(比如域名不存在)或被拒绝(Connection refused)时完全静默 - 如果目标地址是域名,Workerman 默认用系统 gethostbyname,不支持 IPv6 或自定义 DNS;遇到解析慢或失败,建议提前 resolve 好 IP 再传入
tcp://192.168.1.100:8080 - 连接建立后,远端可能立刻断开(如 HTTP 服务收到非 HTTP 数据),这时要靠
onClose捕获,而不是以为“连上了就稳了”
如何正确发送数据并等待响应
AsyncTcpConnection 是纯 TCP 层,没有内置协议解析,你发什么、收什么、什么时候收完,全得自己控制。它不像 cURL 那样封装了 HTTP 状态码和 body 边界。
- 写数据用
$connection->send($data),但不能假设立刻发出去——底层走 eventloop 缓冲,发完不会回调,需监听onBufferFull和onBufferDrain应对背压 - 读响应必须自己定协议边界:比如约定结尾是
\n,就得在onMessage里做缓冲拼接,不能直接把每次$data当完整响应 - 别在
onMessage里调$connection->close()后立刻 new 新连接——eventloop 尚未清理旧资源,容易触发Warning: stream_socket_client(): unable to connect - 如果远端是 Redis/Memcached/MySQL 等二进制协议,必须严格按协议组包、拆包;用错字段长度或 magic byte,对方直接 RST
连接池与并发控制的实际取舍
Workerman 自身不提供 AsyncTcpConnection 连接池,很多人自己套一层数组管理,结果在高并发下出现 fd 耗尽、TIME_WAIT 爆满或 callback 嵌套过深。
- 单个
AsyncTcpConnection实例只能用一次:一旦onClose触发,对象就失效,不能再send或重用,必须 new 新实例 - 想复用连接,得自己维护 pool,但要注意:连接空闲超时(远端主动断开)、心跳保活(
$connection->ping()需自己实现)、以及连接泄漏(忘了从 pool 中 remove) - 并发数别硬写死,用
Worker::$maxConnection或信号量限流;不然 1000 个连接同时发起,DNS 查询和 SYN 包会打爆本地端口或触发内核限制 - Linux 下观察
netstat -ant | grep TIME_WAIT | wc -l,超过 65535 就要调net.ipv4.tcp_tw_reuse,否则新连接直接失败
调试时必须打开的两个开关
Workerman 默认隐藏底层 socket 错误,不打开日志,你看到的只有“没反应”,根本不知道卡在哪一步。
立即学习“PHP免费学习笔记(深入)”;
- 启动前加
define('WORKERMAN_DEBUG', true),让AsyncTcpConnection把 DNS、connect、write、read 的每步状态打到 stdout - 在
onError回调里打印完整$exception->getMessage()和$connection->getRemoteIp(),能区分是“连不到 IP”还是“连到了但被拒绝” - 别信
var_dump($connection)—— 它不显示当前 socket 状态;真要看,用stream_get_meta_data($connection->getSocket())拿timed_out、eof等字段 - 测试阶段用
telnet example.com 80或nc -zv example.com 80先确认基础连通性,排除网络层干扰
异步 TCP 连接真正的复杂点不在怎么写 send/onMessage,而在于你得同时盯住 DNS、TCP 状态机、协议分帧、连接生命周期这四层。少盯一层,问题就藏在黑盒里不动声色。



















