一、项目背景

手写了一个小型计算器服务:自定义协议(长度\r\n + JSON + \r\n)+ 对 socket 的类封装(SocketClass / TCPSocket,服务端 fork 多进程,客户端交互式输入),跨机器部署到两台云服务器上联调:

角色 主机 内网 IP 公网出口 IP
服务端 腾讯云 VM-0-11-ubuntu 10.0.0.11 122.152.208.179
客户端 instance-qhw6x01g 192.168.16.2 180.76.141.212

二、问题与解决(按时间线)

问题一:fail: Connection refused (errno=111, ret=-1)

现象:客户端 ./clientTCP 192.168.16.2 8081 直接报错。

定位过程

  1. errno 111 = ECONNREFUSED,语义是:SYN 包到达了目标机器,但目标端口上没有任何进程在 listen(或被防火墙 RST)——不是网络不通,是"端口上没有服务";
  2. 用 ifconfig 一查发现:192.168.16.2 竟然是客户端自己的 eth0 地址!客户端拿着自己的 IP 去连,自己机器上没有服务在监听 8081,当然被拒;
  3. 服务端其实跑在另一台机器 VM-0-11-ubuntu 上,监听 0.0.0.0:8080,一切正常。

解决:连对目标 IP。

问题二:ping 10.0.0.11 无响应——跨私网不可达(模拟链接)

现象:改成服务端内网 IP 10.0.0.11 后 ping 无任何回复。

定位过程

  1. ip route 一看:客户端只有 192.168.16.0/20 的直连路由和默认网关,根本没有到 10.0.0.0/8 的路由
  2. 两台机器分属不同云环境的私网(腾讯云 10.x vs 实验室 192.168.16.0/20),私网天然隔离,内网 IP 互不可达;
  3. 但两边 curl ifconfig.me 都能出公网 → 都有 NAT 公网出口,走公网 IP 可行

解决:客户端改连服务端公网 IP 122.152.208.179

方法论收获:先看路由表,再判断"通不通";ping 不通不代表 TCP 不通(云平台可能只禁 ICMP),最终以 nc -vz 为准。

问题三:公网 IP 也 refused——云安全组这道"虚拟机外的墙"

现象:连公网 IP 依然 refused。

定位过程

  1. 服务端本机防火墙排查:ufw status → inactive;iptables -L -n → INPUT 策略 ACCEPT,仅有的 3 条 REJECT 是云镜自动封禁的攻击源 IP,与客户端无关——虚拟机内没有任何拦截
  2. 意识到漏了一层:云安全组在宿主机层面过滤,虚拟机内根本看不到
  3. 控制台一查,安全组没有 8080 的入站规则。

解决:腾讯云控制台 → 安全组 → 入站规则添加 TCP 8080-8090 / 来源 0.0.0.0/0 / 允许。规则一加,nc -vz 122.152.208.179 8080 立即 succeeded!

方法论收获:云上排障分层清单:进程监听 → 本机防火墙 → 云安全组 → 路由/公网,一层层排除。

三、方法论总结

  1. 先读懂 errno 再动手:111 = ECONNREFUSED = "端口没有服务在听",把排查方向直接锁定到"谁在监听 + 防火墙";
  2. 网络分层排查清单:进程监听(ss -tlnp)→ 本机防火墙(ufw/iptables)→ 云安全组 → 路由/公网可达性(ip routenc -vz);
  3. 跨云环境不要指望私网互通:不同云厂商私网隔离,走公网 IP + 安全组放行;
  4. 别拿 ping 当 TCP 连通性依据:ICMP 常被云平台丢弃,nc -vz 才是 TCP 的试金石;
  5. 错误处理三原则:接口返回状态、调用处必须检查、成功提示不能无条件打印;
  6. 改完代码必须重新编译并同步二进制,否则排障会被旧版本误导。

更多推荐