1 Star 1 Fork 1

坐公交也用券 / gns

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
ping.go 5.31 KB
一键复制 编辑 原始数据 按行查看 历史
lenove 提交于 2023-04-26 16:03 . 优化依赖
package gns
import (
"errors"
"fmt"
"gitee.com/liumou_site/gcs"
"github.com/spf13/cast"
"math/rand"
"net"
"os"
"runtime"
"strings"
"time"
"gitee.com/liumou_site/logger"
"golang.org/x/net/icmp"
"golang.org/x/net/ipv4"
)
// PingLoss 通过调用系统命令进行ping检测丢包率
func (p *PingCmdAPI) PingLoss(host string, pack int) (err error, loss int) {
loss = 100
var arg []string
arg = append(arg, "ping")
if runtime.GOOS == "windows" {
arg = append(arg, "-n")
} else {
arg = append(arg, "-c")
}
arg = append(arg, cast.ToString(pack))
arg = append(arg, cast.ToString(host))
gc := gcs.NewShell()
gc.RunShell(arg...)
for index, line := range strings.Split(gc.Strings, "\n") {
if strings.Contains(line, "packet loss") {
fmt.Println(index, ": ", line)
parts := strings.Split(line, ", ")
loss = cast.ToInt(strings.TrimSuffix(parts[2], "% packet loss"))
fmt.Printf("丢包率:%s\n", strings.TrimSuffix(parts[2], "% packet loss"))
}
if strings.Contains(line, "% 丢失)") {
fmt.Println(index, ": ", line)
parts := strings.Split(line, ", ")
loss = cast.ToInt(strings.TrimSuffix(parts[2], "% 丢失)"))
fmt.Printf("丢包率:%s\n", strings.TrimSuffix(parts[2], "% packet loss"))
}
}
if err != nil {
fmt.Println(err)
}
return
}
// PingCmd 通过调用系统命令进行ping检测
func (p *PingCmdAPI) PingCmd(host string) error {
p.host = host
_, _, c := p.shellSystem()
return c
}
// Ping 通过net模块构造数据实现icmp请求达到Ping检测主机在线的效果
func Ping(host string, req int, debug bool) error {
var Data = []byte("Test Request Package Information")
ping, err := create(host, req, Data)
ping.debug = debug
if err != nil {
fmt.Println(err)
return err
}
err = ping.icmp(3)
if err != nil {
return err
}
return nil
}
// getIp4 获取远程主机IPV4地址
func getIp4(host string) (string, error) {
adders, err := net.LookupHost(host)
if err != nil {
return "", err
}
if len(adders) < 1 {
return "", errors.New("unknown host")
}
rd := rand.New(rand.NewSource(time.Now().UnixNano()))
//fmt.Println(adders[rd.Intn(len(adders))])
return adders[rd.Intn(len(adders))], nil
}
type Reply struct {
Time int64
TTL uint8
Error error
}
func MarshalMsg(req int, data []byte) ([]byte, error) {
xid, xseq := os.Getpid()&0xffff, req
wm := icmp.Message{
Type: ipv4.ICMPTypeEcho, Code: 0,
Body: &icmp.Echo{
ID: xid, Seq: xseq,
Data: data,
},
}
return wm.Marshal(nil)
}
type ping struct {
Addr string // 需要检测的IPV4地址
Conn net.Conn
Data []byte
debug bool // 显示检测过程信息
}
// dail 发起拨号请求
func (p *ping) dail() (err error) {
p.Conn, err = net.Dial("ip4:icmp", p.Addr)
if err != nil {
logger.Error(err.Error())
return err
}
return nil
}
// SetDeadline 设置截止时间
func (p *ping) SetDeadline(timeout int) error {
return p.Conn.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second))
}
// Close 关闭连接
func (p *ping) Close() error {
return p.Conn.Close()
}
// icmp 开始进行Ping操作
func (p *ping) icmp(count int) error {
if err := p.dail(); err != nil {
return err
}
if p.debug {
fmt.Println("Start ping from ", p.Conn.LocalAddr())
}
err := p.SetDeadline(10)
if err != nil {
return fmt.Errorf("截止时间设置失败")
}
for i := 0; i < count; i++ {
r := msg(p.Conn, p.Data)
if r.Error != nil {
if opt, ok := r.Error.(*net.OpError); ok && opt.Timeout() {
if p.debug {
fmt.Printf("From %s reply: TimeOut\n", p.Addr)
}
if err := p.dail(); err != nil {
err = fmt.Errorf("找不到远程主机")
fmt.Println(err.Error())
return err
}
} else {
if p.debug {
fmt.Printf("From %s reply: %s\n", p.Addr, r.Error)
}
}
return r.Error
} else {
if p.debug {
fmt.Printf("From %s reply: time=%d ttl=%d\n", p.Addr, r.Time, r.TTL)
}
}
time.Sleep(1e9)
}
return nil
}
func (p *ping) PingCount(count int) (reply []Reply) {
if err := p.dail(); err != nil {
fmt.Println("Not found remote host")
return
}
err := p.SetDeadline(10)
if err != nil {
fmt.Println("截止时间设置失败")
return
}
for i := 0; i < count; i++ {
r := msg(p.Conn, p.Data)
reply = append(reply, r)
time.Sleep(1e9)
}
return
}
// create 开始创建实例
func create(addr string, req int, data []byte) (*ping, error) {
wb, err := MarshalMsg(req, data)
if err != nil {
return nil, err
}
addr, err = getIp4(addr)
if err != nil {
return nil, err
}
return &ping{Data: wb, Addr: addr}, nil
}
// 发送Ping消息
func msg(c net.Conn, wb []byte) (reply Reply) {
start := time.Now()
if _, reply.Error = c.Write(wb); reply.Error != nil {
return
}
rb := make([]byte, 1500)
var n int
n, reply.Error = c.Read(rb)
if reply.Error != nil {
return
}
duration := time.Now().Sub(start)
ttl := uint8(rb[8])
rb = func(b []byte) []byte {
if len(b) < 20 {
return b
}
children := int(b[0]&0x0f) << 2
return b[children:]
}(rb)
var rm *icmp.Message
rm, reply.Error = icmp.ParseMessage(1, rb[:n])
if reply.Error != nil {
return
}
switch rm.Type {
case ipv4.ICMPTypeEchoReply:
t := int64(duration / time.Millisecond)
reply = Reply{t, ttl, nil}
case ipv4.ICMPTypeDestinationUnreachable:
reply.Error = errors.New("destination Unreachable")
default:
reply.Error = fmt.Errorf("not ICMPTypeEchoReply %v", rm)
}
return
}
Go
1
https://gitee.com/liumou_site/gns.git
git@gitee.com:liumou_site/gns.git
liumou_site
gns
gns
v1.3.3

搜索帮助

53164aa7 5694891 3bd8fe86 5694891