怎么说呢
这也不是一个完整的Ping过程处理,
更像是一个可以测试Ping服务器的工具。
支持并发,编译完后,可以用ping.exe -help 查看使用说明
上代码吧,
/**
* 邪恶的Ping命令,
* 只发数据报,不接收,而且可以伪造别人的IP
*/
package main
import (
"bytes"
"flag"
"fmt"
"net"
"time"
"runtime"
)
var (
datalen int = 100
timeout int = 10
targethost string = "www.XXXXX.com"
localIp string = "102.23.24.5.135"
times int = 10
concurrent int = 10 //10个并发
)
func doPing(laddr *net.IPAddr, raddr *net.IPAddr, b *[]byte) {
defer func() {
tmp <- true
}()
conn, err := net.DialIP("ip4:icmp", laddr, raddr)
if err != nil {
fmt.Println(err.Error())
return
}
conn.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second))
_, err = conn.Write(*b)
if err != nil {
fmt.Println(err.Error())
}
defer conn.Close()
}
var tmp chan bool
func main() {
flag.StringVar(&targethost, "target", "www.baidu.com", "目标地址")
flag.StringVar(&localIp, "local", "102.23.24.5.135", "发送源地址")
flag.IntVar(&timeout, "timeout", 10, "超时设置,单位秒")
flag.IntVar(&datalen, "datalen", 1024, "携带数据包大小")
flag.IntVar(×, "times", 1, "Ping次数")
flag.IntVar(&concurrent, "concurrent", 1, "并发数,不能小于Ping次数")
flag.Parse()
fmt.Printf("Ping %s\n发送方IP:%s\n,数据长度:%d\n超时:%d秒\n发送次数:%d\n并发数:%d\n", targethost, localIp, datalen, timeout, times, concurrent)
tmp = make(chan bool, concurrent)
runtime.GOMAXPROCS(runtime.NumCPU())
var (
laddr = net.IPAddr{IP: net.ParseIP(localIp)}
raddr, _ = net.ResolveIPAddr("ip", targethost)
)
//直接构造ICMP包,带数据的
b := []byte{8, 0, 0, 0}
b = append(b, bytes.Repeat([]byte("a"), datalen)...)
csumcv := len(b) - 1 // checksum coverage
s := uint32(0)
for i := 0; i < csumcv; i += 2 {
s += uint32(b[i+1])<<8 | uint32(b[i])
}
if csumcv&1 == 0 {
s += uint32(b[csumcv])
}
s = s>>16 + s&0xffff
s = s + s>>16
b[2] ^= byte(^s & 0xff)
b[3] ^= byte(^s >> 8)
start := time.Now()
//使用并发
for i := 0; i < concurrent; i++ {
go doPing(&laddr, raddr, &b)
}
for i := 0; i < times; i++ {
<-tmp
if i < times-concurrent {
go doPing(&laddr, raddr, &b)
}
fmt.Print(".")
}
sub := time.Now().Sub(start) / 1e6
fmt.Println()
fmt.Printf("全部请求发送完成,耗时:%d毫秒", sub)
}