<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>端口 on 豆子技术站</title><link>https://blog.91demo.top/tags/%E7%AB%AF%E5%8F%A3/</link><description>Recent content in 端口 on 豆子技术站</description><generator>Hugo -- 0.155.1</generator><language>zh-cn</language><lastBuildDate>Mon, 05 Feb 2018 12:40:16 +0800</lastBuildDate><atom:link href="https://blog.91demo.top/tags/%E7%AB%AF%E5%8F%A3/index.xml" rel="self" type="application/rss+xml"/><item><title>实战笔记：当我想查端口却没装 Telnet 时，我决定自己写个工具</title><link>https://blog.91demo.top/check-port/</link><pubDate>Mon, 05 Feb 2018 12:40:16 +0800</pubDate><guid>https://blog.91demo.top/check-port/</guid><description>&lt;p&gt;作为开发者，你一定遇到过这种“抓狂”的时刻：&lt;/p&gt;
&lt;p&gt;某次我急需确认服务器上的一个端口是否正常开启，习惯性地打开 Windows 命令行准备敲下 &lt;code&gt;telnet&lt;/code&gt; 命令。结果弹出的却是：“telnet 不是内部或外部命令”。&lt;/p&gt;
&lt;p&gt;由于系统刚重装，这个组件还没勾选。当我从控制面板找到它、安装、甚至可能还要重启系统时，这套复杂的操作让我陷入了反思：&lt;strong&gt;为了检测一个端口，至于这么麻烦吗？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;更进一步想，如果我手头没有电脑，只有一部手机，我该如何快速判断服务器防火墙是不是忘了开？&lt;/p&gt;
&lt;h3 id="痛点环境依赖与生态限制"&gt;痛点：环境依赖与生态限制&lt;/h3&gt;
&lt;p&gt;在实现这个功能之前，我有过两个思考维度：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;环境依赖&lt;/strong&gt;：无论是 Windows 的 Telnet 还是 Linux 的 &lt;code&gt;nc&lt;/code&gt;，都依赖当前操作系统的环境配置。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;小程序限制&lt;/strong&gt;：微信小程序虽然有网络请求能力，但它必须配置服务器域名白名单。如果你想直接用小程序前端去探测一个随机的 IP 或端口，微信的底层安全机制是不允许的。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="方案go-后端代劳小程序只做遥控器"&gt;方案：Go 后端代劳，小程序只做“遥控器”&lt;/h3&gt;
&lt;p&gt;为了绕过这些限制，我在“豆子工具”里实现了一个&lt;strong&gt;远程端口检测&lt;/strong&gt;功能。它的逻辑非常直接且高效：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;前端交互&lt;/strong&gt;：用户只需在小程序里输入目标服务器的 &lt;strong&gt;IP/域名&lt;/strong&gt; 和 &lt;strong&gt;端口号&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;后端核心&lt;/strong&gt;：数据提交到我用 &lt;strong&gt;Go&lt;/strong&gt; 编写的后端服务。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;模拟连接&lt;/strong&gt;：后端服务代替用户执行 TCP 连接探测。Go 语言的 &lt;code&gt;net.DialTimeout&lt;/code&gt; 在这里非常实用，可以精准控制探测时间，避免由于网络超时导致的页面死等。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;结果反馈&lt;/strong&gt;：后端将“连接成功”或“连接失败”的结果返回给小程序展示。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="服务端口检测" loading="lazy" src="https://blog.91demo.top/images/wander/tool-chkport.webp"&gt;&lt;/p&gt;
&lt;h3 id="价值随时随地的运维眼"&gt;价值：随时随地的“运维眼”&lt;/h3&gt;
&lt;p&gt;自从这个功能上线后，我解决了很多尴尬的场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;排查防火墙&lt;/strong&gt;：在云厂商后台改了安全组策略后，掏出手机点一下，秒知是否生效。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;现场交付&lt;/strong&gt;：在客户现场没有电脑时，快速确认后端服务是否已经拉起。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;零部署成本&lt;/strong&gt;：再也不用担心当前电脑有没有装 Telnet 或 Netcat。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="技术实现"&gt;技术实现&lt;/h3&gt;
&lt;p&gt;这里的难点在于服务器端实现，小程序端仅仅提交FORM表单就可以了。下面我们看看服务端的Go的核心实现：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;// 检测端口是否被打开？
func IsPortOpened(ip string, port int) bool {
addr := net.JoinHostPort(ip, fmt.Sprintf(&amp;#34;%d&amp;#34;, port))
conn, err := net.DialTimeout(&amp;#34;tcp&amp;#34;, addr, time.Second*3)
if err != nil {
return false
}
if conn != nil {
conn.Close()
return true
}
return false
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这里仅能探测TCP端口，UDP端口我还没有思路，等有思路了我再在这篇文章里补充。&lt;/p&gt;</description></item></channel></rss>