go实现fping功能

本文介绍了如何使用Go语言实现fping的功能,包括理解fping的基本概念,详细阐述了实现思路,以及具体展示了如何获取IP段和实现ping操作。

1、什么是fping

fping 是一个类似 ping 的程序,与 ping 不同的是你可以同时指定多个要 ping 的目标。
fping 发送完 ping 包后不等待回应,而是继续下一个目标

2、实现思路

1、获取IP段
2、写一个ping方法
3、将IP段分解成一个个的IP
4、用协程一个个去ping这些IP

3、具体实现

  1. 获取IP段
// IP段
'1', '2020-11-26 17:11:39.515', '2020-11-26 17:11:39.515', '1.0.1.0', '1.0.3.255', '福建', '电信'
'2', '2020-11-26 17:11:43.553', '2020-11-26 17:11:43.553', '1.0.8.0', '1.0.15.255', '广东', '电信'
'3', '2020-11-26 17:11:47.563', '2020-11-26 17:11:47.563', '1.0.32.0', '1.0.63.255', '广东', '电信'
'4', '2020-11-26 17:11:53.621', '2020-11-26 17:11:53.621', '1.1.0.0', '1.1.0.255', '福建', '电信'
'5', '2020-11-26 17:11:57.635', '2020-11-26 17:11:57.635', '1.1.2.0', '1.1.7.255', '福建', '电信'
'6', '2020-11-26 17:11:59.642', '2020-11-26 17:11:59.642', '1.1.8.0', '1.1.63.255', '广东', '电信'
'7', '2020-11-26 17:12:05.671', '2020-11-26 17:12:05.671', '1.2.0.0', '1.2.1.255', '福建', '电信'
'8', '2020-11-26 17:12:07.674', '2020-11-26 17:12:07.674', '1.2.2.0', '1.2.2.255', '北京', '联通'
'9', '2020-11-26 17:12:13.690', '2020-11-26 17:12:13.690', '1.2.5.0', '1.2.7.255', '北京', '电信'

  1. ping方法(单个,多个已给出)
// 单个ping
// IsAlivePing : 检测目标IP是否能够ping通,target为目标IP
func IsAlivePing(target string) (bool, error) {
	pinger, err := ping.NewPinger(target)
	if err != nil {
		return false, err
	}
	pinger.Count = 10
	PINGTIME := time.Duration(1000)
	pinger.Timeout = time.Duration(PINGTIME * time.Millisecond)
	pinger.SetPrivileged(true) // 选择icmp,不选择udp
	pinger.Run()
	stats := pinger.Statistics()
	// 判断是否有接收到的包
	if stats.PacketsRecv >= 1 {
		return true, nil
	}
	return false, nil
}

// 多个ping:得到死IP
// FilterActiveIPs : 过滤活IP,筛选出死IP
func FilterActiveIPs(ips []string) (inactiveIPs []string) {
	var lock sync.Mutex
	var wg sync.WaitGroup
	wg.Add(len(ips))
	for _, ip := range ips {
		go func(ip string) {
			defer wg.Done()
			// 判断是死ip,并且格式正确
			isAlive, err := IsAlivePing(ip)
			if !isAlive && err == nil {
				RandomSleep(2) // 睡眠[1,2]秒,二次确认是否为死IP
				if isAlive, _ := IsAlivePing(ip); !isAlive {
					RandomSleep(2) // 再睡眠[1,2]秒,三次确认是否为死IP
					if isAlive, _ := IsAlivePing(ip); !isAlive {
						lock.Lock()
						defer lock.Unlock()
						inactiveIPs = append(inactiveIPs, ip)
					}
				}
			}
		}(ip)
	}
	wg.Wait()
	return inactiveIPs
}

// 多个ping:得到活IP
// FilterInactiveIPs : 过滤死IP,筛选出活IP
func FilterInactiveIPs(ips []string) (activeIPs []string) {
	var lock sync.Mutex
	var wg sync.WaitGroup
	wg.Add(len(ips))
	for _, ip := range ips {
		go func(ip string) {
			defer wg.Done()
			// 判断是活ip,并且格式正确
			if isAlive, err := IsAlivePing(ip); isAlive && err == nil {
				lock.Lock()
				defer lock.Unlock()
				activeIPs = append(activeIPs, ip)
			}
		}(ip)
	}
	wg.Wait()
	return activeIPs
}

// RandomSleep : 随机睡眠[1,t]秒
func RandomSleep(t int) {
	rand.Seed(time.Now().UnixNano())
	r := time.Duration(rand.Intn(t) + 1)
	time.Sleep(r * time.Second)
}
  1. 分解IP段
// Separation : 分解IP段
func (i *impl) Separation(minIP, maxIP string) []string {
	shouldStrs := make([]string, 0) // 这是IP段的所有IP
	// for i := 0; i < l; i = i + 2 {
	min, _ := IPString2Long(minIP) // 这里有一个转化,我默认给的是正确的IP,如果兄弟们不确定传入的IP格式是否正确,那么要判断err
	max, _ := IPString2Long(maxIP)
	for min <= max {
		minIPstr, _ := Long2IPString(min)
		xxxip := net.ParseIP(minIPstr).To4()
		if xxxip[3] != 0 && xxxip[3] != 255 { // 兄弟们,这个判断取决于你们想不想要两个端点
			shouldStrs = append(shouldStrs, minIPstr)
		}
		min++
	}

    // TODO: 兄弟们,可以把这句删除了
	fmt.Printf("IP段%s--%s不包括两端的长度: %d\n", minIP, maxIP, len(shouldStrs))
	return shouldStrs
}

// Long2IPString 把数值转为ip字符串
func Long2IPString(i uint) (string, error) {
	if i > math.MaxUint32 {
		return "", errors.New("beyond the scope of ipv4")
	}

	ip := make(net.IP, net.IPv4len)
	ip[0] = byte(i >> 24)
	ip[1] = byte(i >> 16)
	ip[2] = byte(i >> 8)
	ip[3] = byte(i)

	return ip.String(), nil
}

// IPString2Long 把ip字符串转为数值
func IPString2Long(ip string) (uint, error) {
	b := net.ParseIP(ip).To4()
	if b == nil {
		return 0, errors.New("invalid ipv4 format")
	}

	return uint(b[3]) | uint(b[2])<<8 | uint(b[1])<<16 | uint(b[0])<<24, nil
}
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值