Golang如何检测端口状态
Golang如何检测端口状态 我想检查端口状态。我知道有很多端口扫描器的实现,但大多数实现仅在没有抛出错误时假定端口是开放的,否则就认为不是。
func GetPortState(network string, address string, timeoutInMilliseconds int) {
timeout := time.Duration(timeoutInMilliseconds) * time.Millisecond
connection, connectionError := net.DialTimeout(network, address, timeout)
if connectionError != nil {
// inspect error
// return state ...
}
defer func() {
connectionCloseError := connection.Close()
if connectionCloseError != nil {
// return error
}
}()
// return state
}
有人能帮忙实现这个函数,使其正常工作吗?
提前感谢
更多关于Golang如何检测端口状态的实战教程也可以访问 https://www.itying.com/category-94-b0.html
2 回复
它们中的大多数仅假设在没有抛出错误的情况下端口是开放的,否则就不是。
那么,你是如何定义一个开放端口的呢?
更多关于Golang如何检测端口状态的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
要实现一个可靠的端口状态检测函数,需要处理多种网络错误情况。以下是完整的实现示例:
package main
import (
"errors"
"fmt"
"net"
"strings"
"time"
)
type PortState int
const (
PortOpen PortState = iota
PortClosed
PortFiltered
PortError
)
func GetPortState(network string, address string, timeoutInMilliseconds int) (PortState, error) {
timeout := time.Duration(timeoutInMilliseconds) * time.Millisecond
conn, err := net.DialTimeout(network, address, timeout)
if err != nil {
// 分析错误类型以确定端口状态
errStr := err.Error()
// 连接被拒绝通常表示端口关闭
if strings.Contains(errStr, "connection refused") {
return PortClosed, nil
}
// 超时通常表示端口被过滤
if strings.Contains(errStr, "timeout") ||
strings.Contains(errStr, "i/o timeout") {
return PortFiltered, nil
}
// 网络不可达
if strings.Contains(errStr, "no route to host") ||
strings.Contains(errStr, "network is unreachable") {
return PortFiltered, err
}
// 其他错误
return PortError, err
}
defer func() {
if conn != nil {
conn.Close()
}
}()
return PortOpen, nil
}
// 辅助函数,获取可读的状态描述
func (ps PortState) String() string {
switch ps {
case PortOpen:
return "OPEN"
case PortClosed:
return "CLOSED"
case PortFiltered:
return "FILTERED"
case PortError:
return "ERROR"
default:
return "UNKNOWN"
}
}
// 使用示例
func main() {
// 测试常见端口
testCases := []struct {
network string
address string
timeout int
}{
{"tcp", "google.com:80", 3000},
{"tcp", "localhost:22", 1000},
{"tcp", "127.0.0.1:9999", 2000},
{"tcp", "192.168.1.1:80", 1000},
}
for _, tc := range testCases {
state, err := GetPortState(tc.network, tc.address, tc.timeout)
fmt.Printf("检查 %s://%s\n", tc.network, tc.address)
fmt.Printf("状态: %s", state)
if err != nil {
fmt.Printf(" 错误: %v", err)
}
fmt.Println()
fmt.Println("---")
}
}
对于更精确的错误处理,可以使用类型断言:
func GetPortStateWithDetailedError(network string, address string, timeoutInMilliseconds int) (PortState, error) {
timeout := time.Duration(timeoutInMilliseconds) * time.Millisecond
conn, err := net.DialTimeout(network, address, timeout)
if err != nil {
var netErr net.Error
var opErr *net.OpError
switch {
case errors.As(err, &netErr) && netErr.Timeout():
return PortFiltered, nil
case errors.As(err, &opErr):
// 检查操作错误的具体类型
if opErr.Op == "dial" {
if strings.Contains(opErr.Err.Error(), "connection refused") {
return PortClosed, nil
}
}
return PortError, err
default:
return PortError, err
}
}
defer conn.Close()
return PortOpen, nil
}
如果需要检查UDP端口状态:
func CheckUDPPort(address string, timeoutInMilliseconds int) (PortState, error) {
timeout := time.Duration(timeoutInMilliseconds) * time.Millisecond
udpAddr, err := net.ResolveUDPAddr("udp", address)
if err != nil {
return PortError, err
}
conn, err := net.DialUDP("udp", nil, udpAddr)
if err != nil {
return PortError, err
}
defer conn.Close()
conn.SetDeadline(time.Now().Add(timeout))
// 发送测试数据(可选)
_, err = conn.Write([]byte{0x00})
if err != nil {
return PortError, err
}
// 尝试读取响应
buffer := make([]byte, 1024)
_, err = conn.Read(buffer)
if err != nil {
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
// UDP无响应通常表示端口开放或被过滤
return PortOpen, nil
}
return PortError, err
}
return PortOpen, nil
}
这个实现提供了:
- 明确的端口状态枚举
- 详细的错误分析
- 支持TCP和UDP协议
- 可配置的超时时间
- 清晰的错误分类

