init: repository
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
*.exe
|
||||||
|
|
||||||
|
tcping
|
||||||
17
README.md
Normal file
17
README.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Tcping GO
|
||||||
|
|
||||||
|
一个使用go写的小工具,用于检测TCP端口是否开放。
|
||||||
|
|
||||||
|
## 使用方法
|
||||||
|
|
||||||
|
```shell
|
||||||
|
tcping -h
|
||||||
|
|
||||||
|
Usage of tcping:
|
||||||
|
-c, --count int 测试次数,默认为4次 (default 4)
|
||||||
|
-h, --help 显示帮助信息
|
||||||
|
-t, --infinite 无限次测试
|
||||||
|
-6, --ipv6 使用 IPv6,需搭配域名使用
|
||||||
|
-p, --port int 端口,默认为80 (default 80)
|
||||||
|
-s, --timeout duration 超时时间,默认为2秒 (default 2s)
|
||||||
|
```
|
||||||
5
go.mod
Normal file
5
go.mod
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module tcping
|
||||||
|
|
||||||
|
go 1.22.1
|
||||||
|
|
||||||
|
require github.com/spf13/pflag v1.0.5
|
||||||
2
go.sum
Normal file
2
go.sum
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
142
main.go
Normal file
142
main.go
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
flag "github.com/spf13/pflag"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var (
|
||||||
|
port int
|
||||||
|
count int
|
||||||
|
timeoutDuration time.Duration
|
||||||
|
infinite bool
|
||||||
|
ipv6 bool
|
||||||
|
|
||||||
|
successCount int
|
||||||
|
attemptCount int
|
||||||
|
stopped bool
|
||||||
|
)
|
||||||
|
|
||||||
|
// 设置命令行参数
|
||||||
|
help := flag.BoolP("help", "h", false, "显示帮助信息")
|
||||||
|
flag.IntVarP(&port, "port", "p", 80, "端口,默认为80")
|
||||||
|
flag.IntVarP(&count, "count", "c", 4, "测试次数,默认为4次")
|
||||||
|
flag.DurationVarP(&timeoutDuration, "timeout", "s", 2*time.Second, "超时时间,默认为2秒")
|
||||||
|
flag.BoolVarP(&infinite, "infinite", "t", false, "无限次测试")
|
||||||
|
flag.BoolVarP(&ipv6, "ipv6", "6", false, "使用 IPv6,需搭配域名使用")
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if *help {
|
||||||
|
flag.Usage()
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
args := flag.Args()
|
||||||
|
if len(args) < 1 {
|
||||||
|
flag.Usage()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if port < 1 || port > 65535 {
|
||||||
|
fmt.Println("端口号必须在1-65535之间")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
hostname := args[0]
|
||||||
|
|
||||||
|
// 设置信号捕获
|
||||||
|
stopped = false
|
||||||
|
sigChan := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
|
||||||
|
ip := ""
|
||||||
|
|
||||||
|
if net.ParseIP(hostname) == nil {
|
||||||
|
// 解析域名
|
||||||
|
ips, err := net.LookupIP(hostname)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("解析 %s 失败: %s\n", hostname, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
record := "A"
|
||||||
|
if ipv6 {
|
||||||
|
record = "AAAA"
|
||||||
|
}
|
||||||
|
ip, err = filterIP(ips, ipv6)
|
||||||
|
if (err != nil) {
|
||||||
|
fmt.Printf("找不到 %s 的 %s 记录\n", hostname, record)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
fmt.Printf("使用 %s 的 %s 记录: %s\n", hostname, record, ip)
|
||||||
|
} else {
|
||||||
|
ip = hostname
|
||||||
|
}
|
||||||
|
|
||||||
|
address := net.JoinHostPort(ip, fmt.Sprintf("%d", port))
|
||||||
|
|
||||||
|
if infinite {
|
||||||
|
count = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
done := make(chan bool, 1)
|
||||||
|
go func() {
|
||||||
|
for i := 0; infinite || i < count; i++ {
|
||||||
|
start := time.Now()
|
||||||
|
conn, err := net.DialTimeout("tcp", address, timeoutDuration)
|
||||||
|
duration := time.Since(start)
|
||||||
|
attemptCount++
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("测试到 %s 的连接失败: %s\n", address, "连接超时")
|
||||||
|
} else {
|
||||||
|
successCount++
|
||||||
|
fmt.Printf("[%d] 来自 %s 的响应: 时间=%s\n",i+1, address, fmt.Sprintf("%.3fms", float64(duration)/float64(time.Millisecond)))
|
||||||
|
conn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
if !infinite && attemptCount >= count {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
}
|
||||||
|
done <- true
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 等待信号或测试完成
|
||||||
|
select {
|
||||||
|
case <-sigChan:
|
||||||
|
fmt.Println("\n测试被用户中断")
|
||||||
|
stopped = true
|
||||||
|
case <-done:
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打印统计结果
|
||||||
|
if !stopped {
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
fmt.Printf("测试完成,成功次数: %d/%d\n", successCount, attemptCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
func filterIP(ips []net.IP, ipv6 bool) (string, error) {
|
||||||
|
if ipv6 {
|
||||||
|
for _, ip := range ips {
|
||||||
|
if ip.To16() != nil && ip.To4() == nil {
|
||||||
|
return ip.String(), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, ip := range ips {
|
||||||
|
if ip.To4() != nil && ip.To16() != nil {
|
||||||
|
return ip.String(), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("找不到合适的IP地址")
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user