作为开发者,你一定遇到过这种“抓狂”的时刻:

某次我急需确认服务器上的一个端口是否正常开启,习惯性地打开 Windows 命令行准备敲下 telnet 命令。结果弹出的却是:“telnet 不是内部或外部命令”。

由于系统刚重装,这个组件还没勾选。当我从控制面板找到它、安装、甚至可能还要重启系统时,这套复杂的操作让我陷入了反思:为了检测一个端口,至于这么麻烦吗?

更进一步想,如果我手头没有电脑,只有一部手机,我该如何快速判断服务器防火墙是不是忘了开?

痛点:环境依赖与生态限制

在实现这个功能之前,我有过两个思考维度:

  1. 环境依赖:无论是 Windows 的 Telnet 还是 Linux 的 nc,都依赖当前操作系统的环境配置。
  2. 小程序限制:微信小程序虽然有网络请求能力,但它必须配置服务器域名白名单。如果你想直接用小程序前端去探测一个随机的 IP 或端口,微信的底层安全机制是不允许的。

方案:Go 后端代劳,小程序只做“遥控器”

为了绕过这些限制,我在“豆子工具”里实现了一个远程端口检测功能。它的逻辑非常直接且高效:

  • 前端交互:用户只需在小程序里输入目标服务器的 IP/域名端口号
  • 后端核心:数据提交到我用 Go 编写的后端服务。
  • 模拟连接:后端服务代替用户执行 TCP 连接探测。Go 语言的 net.DialTimeout 在这里非常实用,可以精准控制探测时间,避免由于网络超时导致的页面死等。
  • 结果反馈:后端将“连接成功”或“连接失败”的结果返回给小程序展示。

服务端口检测

价值:随时随地的“运维眼”

自从这个功能上线后,我解决了很多尴尬的场景:

  • 排查防火墙:在云厂商后台改了安全组策略后,掏出手机点一下,秒知是否生效。
  • 现场交付:在客户现场没有电脑时,快速确认后端服务是否已经拉起。
  • 零部署成本:再也不用担心当前电脑有没有装 Telnet 或 Netcat。

技术实现

这里的难点在于服务器端实现,小程序端仅仅提交FORM表单就可以了。下面我们看看服务端的Go的核心实现:

// 检测端口是否被打开?
func IsPortOpened(ip string, port int) bool {
	addr := net.JoinHostPort(ip, fmt.Sprintf("%d", port))
	conn, err := net.DialTimeout("tcp", addr, time.Second*3)

	if err != nil {
		return false
	}

	if conn != nil {
		conn.Close()
		return true
	}

	return false
}

这里仅能探测TCP端口,UDP端口我还没有思路,等有思路了我再在这篇文章里补充。

总结

很多时候,工具的意义并不在于它用了多么高深的算法,而在于它是否能在你最需要的时候,以最简单的方式解决那个微小却刺手的痛点。