1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
| package main
import ( "bytes" "encoding/binary" "flag" "fmt" "log" "math" "net" "os" "time" )
var ( timeout int64 size int count int typ uint8 = 8 code uint8 = 0 sendCount int successCount int failCount int minTx int64 = math.MaxInt64 maxTx int64 = math.MinInt32 totalTx int64 = 0 )
type ICMP struct { Type uint8 Code uint8 CheckSum uint16 ID uint16 SequenceNum uint16 }
func main() { parseCommandArgs() desIp := os.Args[len(os.Args)-1] conn, err := net.DialTimeout("ip:icmp", desIp, time.Duration(timeout)*time.Millisecond) if err != nil { log.Fatal(err) } defer conn.Close() fmt.Printf("正在 Ping %s [%s] 具有 %d 字节的数据:\n", desIp, conn.RemoteAddr(), size) for i := 0; i < count; i++ { sendCount++ startTime := time.Now() icmp := &ICMP{ Type: typ, Code: code, CheckSum: 0, ID: 1, SequenceNum: 1, } data := make([]byte, size) var buffer bytes.Buffer binary.Write(&buffer, binary.BigEndian, icmp) buffer.Write(data) data = buffer.Bytes() checkSum := checkSum(data) data[2] = byte(checkSum >> 8) data[3] = byte(checkSum)
conn.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Millisecond)) n, err := conn.Write(data) if err != nil { failCount++ log.Println("write err:", err) continue } buf := make([]byte, 65535) n, err = conn.Read(buf) if err != nil { failCount++ log.Println("read err:", err) continue } ts := time.Since(startTime).Milliseconds() successCount++ totalTx += ts if minTx > ts { minTx = ts } if maxTx < ts { maxTx = ts } fmt.Printf("来自 %d.%d.%d.%d 的回复: 字节=%d 时间=%d ms TTL=%d\n", buf[12], buf[13], buf[14], buf[15], n-28, ts, buf[8]) time.Sleep(time.Second)
} fmt.Printf("%s 的 Ping 统计信息:\n 数据包: 已发送 = %d,已接收 = %d,丢失 = %d (%.2f%% 丢失),\n往返行程的估计时间(以毫秒为单位):\n 最短 = %dms,最长 = %dms,平均 = %dms", conn.RemoteAddr(), sendCount, successCount, failCount, float64(failCount)/float64(sendCount), minTx, maxTx, totalTx/int64(sendCount))
}
func parseCommandArgs() { flag.Int64Var(&timeout, "w", 1000, "请求超时时长,单位ms") flag.IntVar(&size, "l", 32, "请求缓冲区大小,单位字节") flag.IntVar(&count, "n", 4, "发送请求数") flag.Parse() }
func checkSum(data []byte) uint16 { length := len(data) index := 0 var sum uint32 for length > 1 { sum += uint32(data[index])<<8 + uint32(data[index+1]) length -= 2 index += 2 } if length != 0 { sum += uint32(data[index]) } h16 := sum >> 16 for h16 != 0 { sum = h16 + uint32(uint16(sum)) h16 = sum >> 16 } return uint16(^sum) }
|