1 Star 1 Fork 0

李爽/go-utils

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
network.go 6.25 KB
一键复制 编辑 原始数据 按行查看 历史
李爽 提交于 2024-04-09 09:34 . 修改IP地址和整型转换函数
package utils
import (
"encoding/binary"
"fmt"
"net"
"net/url"
"os/exec"
"runtime"
"strconv"
"time"
)
// IsValidIP
// 检测IP地址是否合法
func IsValidIP(ipAddr string) bool {
return net.ParseIP(ipAddr) != nil
}
// IsValidPort
// 检测端口是否合法
func IsValidPort(port string) (int, error) {
p, err := strconv.Atoi(port)
if err != nil {
return 0, fmt.Errorf("port conversion error: %v", err)
}
if p < 1 || p > 65535 {
return 0, fmt.Errorf("port number out of range: %d", p)
}
return p, nil
}
// IsValidURL
// 检测给定字符串是否是一个合法的URL。
func IsValidURL(u string) bool {
// 尝试解析URL
parsed, err := url.ParseRequestURI(u)
if err != nil {
return false // 解析失败意味着这不是一个合法的URL
}
// 判断解析后的URL是否包含Host字段,常用来判断URL是否合法
return parsed.Scheme != "" && parsed.Host != ""
}
// Ping
// 对目的地址发起ping检测icmp是否通畅(只支持ipv4)
func Ping(ipAddr string) bool {
var cmd *exec.Cmd
// 根据操作系统选择不同的ping命令和参数
switch runtime.GOOS {
case "windows":
// Windows的ping命令是 "ping -n 3"
cmd = exec.Command("ping", "-n", "3", "-w", "1", ipAddr)
case "linux":
// Linux的ping命令是 "ping -c 3"
cmd = exec.Command("ping", "-c", "3", "-i", "1", ipAddr)
default:
return false
}
// 执行ping命令
if err := cmd.Run(); err != nil {
// 如果ping命令执行后返回错误,则认为主机不通
return false
}
// 如果ping命令执行成功,没有返回错误,则认为主机通畅
return true
}
//func Ping(ipAddr string, timeout time.Duration, id int) (bool, error) {
// // 监听IPv4的ICMP数据包
// conn, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
// if err != nil {
// return false, fmt.Errorf("无法打开ICMP: %w", err)
// }
// defer func(conn *icmp.PacketConn) {
// _ = conn.Close()
// }(conn)
//
// // 设置Deadline,用于超时控制
// err = conn.SetDeadline(time.Now().Add(timeout))
// if err != nil {
// return false, fmt.Errorf("设置超时失败: %w", err)
// }
//
// // 创建ICMP回显请求消息
// message := icmp.Message{
// Type: ipv4.ICMPTypeEcho, // 在IPv4中,回显请求是类型8
// Code: 0,
// Body: &icmp.Echo{
// ID: id, // 使用传入的id作为ICMP请求的ID
// Seq: 1, // 序列号设置为1
// Data: []byte("Hello"), // 数据部分可以包含自定义的消息
// },
// }
//
// // 将消息封装成字节序列
// binaryMessage, err := message.Marshal(nil)
// if err != nil {
// return false, fmt.Errorf("无法创建ICMP消息: %w", err)
// }
//
// // 解析目标地址
// dst, err := net.ResolveIPAddr("ip4", ipAddr)
// if err != nil {
// return false, fmt.Errorf("无法解析目标IP地址: %w", err)
// }
//
// // 发送ICMP回显请求
// if _, err := conn.WriteTo(binaryMessage, dst); err != nil {
// return false, fmt.Errorf("发送ICMP请求失败: %w", err)
// }
//
// // 读取返回的ICMP回显回复
// reply := make([]byte, 1500)
// n, _, err := conn.ReadFrom(reply)
// if err != nil {
// var netErr net.Error
// if errors.As(err, &netErr) && netErr.Timeout() {
// return false, nil // 超时意味着没有回复,但不是错误
// }
// return false, fmt.Errorf("读取ICMP回复失败: %w", err)
// }
//
// // 解析ICMP回显回复消息
// rm, err := icmp.ParseMessage(1, reply[:n])
// if err != nil {
// return false, fmt.Errorf("解析ICMP回复消息失败: %w", err)
// }
//
// switch rm.Type {
// case ipv4.ICMPTypeEchoReply:
// echoReply, ok := rm.Body.(*icmp.Echo)
// if !ok {
// return false, fmt.Errorf("ICMP回复消息体断言失败")
// }
// if echoReply.ID != id {
// return false, fmt.Errorf("ICMP回复消息ID不匹配: got %d, want %d", echoReply.ID, id)
// }
// return true, nil
// default:
// return false, fmt.Errorf("非预期的ICMP回复类型: got %v, want %v", rm.Type, ipv4.ICMPTypeEchoReply)
// }
//}
// DetectTcpPort
// 检测Tcp端口是否开通
func DetectTcpPort(ip string, port int, timeout time.Duration) bool {
address := fmt.Sprintf("%s:%d", ip, port)
conn, err := net.DialTimeout("tcp", address, timeout)
if err != nil {
return false
}
// 建立后关闭连接
defer func(conn net.Conn) {
_ = conn.Close()
}(conn)
return true
}
// CalculateNetwork
// 根据给定的IP地址和子网掩码计算网络地址
func CalculateNetwork(ipAddr, subnetMask string) (string, error) {
// 解析IP地址和子网掩码
ip := net.ParseIP(ipAddr)
if ip == nil {
return "", fmt.Errorf("invalid IP address format")
}
mask := net.IPMask(net.ParseIP(subnetMask)[12:])
if mask == nil {
return "", fmt.Errorf("invalid subnet mask format")
}
// 计算网络地址
network := net.IPNet{IP: ip.Mask(mask), Mask: mask}
return network.IP.String(), nil
}
// SubNetMaskToBits
// 将子网掩码转换为掩码位数
func SubNetMaskToBits(subnetMask string) (int, error) {
ip := net.ParseIP(subnetMask)
if ip == nil {
return 0, fmt.Errorf("invalid subnet mask")
}
// 将IP地址转换为4字节(对于IPv4)或16字节(对于IPv6)的表示
mask := ip.To4()
if mask == nil {
return 0, fmt.Errorf("invalid IPv4 subnet mask")
}
// 计算子网掩码中1的总数
bits := 0
for _, octet := range mask {
for octet > 0 {
bits += int(octet & 1) // 如果最低位是1,计数器增加
octet >>= 1 // 向右移位,检查下一个位
}
}
return bits, nil
}
// BitsToSubNetMask
// 将掩码位数转换为子网掩码
func BitsToSubNetMask(maskBits int) (string, error) {
if maskBits < 0 || maskBits > 32 {
return "", fmt.Errorf("invalid subnet bits: %d", maskBits)
}
// 根据掩码位计算子网掩码
var mask uint32 = ^uint32(0) << (32 - maskBits)
return fmt.Sprintf("%d.%d.%d.%d", mask>>24, (mask>>16)&0xFF, (mask>>8)&0xFF, mask&0xFF), nil
}
// IpToUint32
// 将IP地址转换为整数
func IpToUint32(ipStr string) (uint32, error) {
ip := net.ParseIP(ipStr)
if ip == nil {
return 0, fmt.Errorf("invalid IP format")
}
ipv4 := ip.To4()
if ipv4 == nil {
return 0, fmt.Errorf("not an IPv4 address")
}
return binary.BigEndian.Uint32(ipv4), nil
}
// Uint32ToIP
// 将整数转换为IP地址
func Uint32ToIP(ipInt uint32) string {
ipBytes := make([]byte, 4)
binary.BigEndian.PutUint32(ipBytes, ipInt)
return net.IP(ipBytes).String()
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/love_bass/go-utils.git
git@gitee.com:love_bass/go-utils.git
love_bass
go-utils
go-utils
v0.4.8

搜索帮助