go语言ping实现

Posted Golang语言社区

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了go语言ping实现相关的知识,希望对你有一定的参考价值。

  1. package main


  2. import (

  3.         "flag"

  4.         "fmt"

  5.         "net"

  6.         "os"

  7.         "strconv"

  8.         "time"

  9. )


  10. func main() {

  11.         var count int

  12.         var timeout int64

  13.         var size int

  14.         var neverstop bool


  15.         flag.Int64Var(&timeout, "w", 1000, "等待每次回复的超时时间(毫秒)。")

  16.         flag.IntVar(&count, "n", 4, "要发送的回显请求数。")

  17.         flag.IntVar(&size, "l", 32, "要发送缓冲区大小。")

  18.         flag.BoolVar(&neverstop, "t", true, "Ping 指定的主机,直到停止。")


  19.         flag.Parse()

  20.         args := flag.Args()


  21.         if len(args) < 1 {

  22.                 fmt.Println("Usage: ", os.Args[0], "host")

  23.                 flag.PrintDefaults()

  24.                 flag.Usage()

  25.                 os.Exit(1)

  26.         }


  27.         ch := make(chan int)

  28.         argsmap := map[string]interface{}{}


  29.         argsmap["w"] = timeout

  30.         argsmap["n"] = count

  31.         argsmap["l"] = size

  32.         argsmap["t"] = neverstop


  33.         for _, host := range args {

  34.                 go ping(host, ch, argsmap)

  35.         }


  36.         for i := 0; i < len(args); i++ {

  37.                 <-ch

  38.         }


  39.         os.Exit(0)

  40. }


  41. func ping(host string, c chan int, args map[string]interface{}) {

  42.         var count int

  43.         var size int

  44.         var timeout int64

  45.         var neverstop bool

  46.         count = args["n"].(int)

  47.         size = args["l"].(int)

  48.         timeout = args["w"].(int64)

  49.         neverstop = args["t"].(bool)


  50.         cname, _ := net.LookupCNAME(host)

  51.         starttime := time.Now()

  52.         conn, err := net.DialTimeout("ip4:icmp", host, time.Duration(timeout*1000*1000))

  53.         ip := conn.RemoteAddr()

  54.         fmt.Println("正在 Ping " + cname + " [" + ip.String() + "] 具有 32 字节的数据:")


  55.         var seq int16 = 1

  56.         id0, id1 := genidentifier(host)

  57.         const ECHO_REQUEST_HEAD_LEN = 8


  58.         sendN := 0

  59.         recvN := 0

  60.         lostN := 0

  61.         shortT := -1

  62.         longT := -1

  63.         sumT := 0


  64.         for count > 0 || neverstop {

  65.                 sendN++

  66.                 var msg []byte = make([]byte, size+ECHO_REQUEST_HEAD_LEN)

  67.                 msg[0] = 8                        // echo

  68.                 msg[1] = 0                        // code 0

  69.                 msg[2] = 0                        // checksum

  70.                 msg[3] = 0                        // checksum

  71.                 msg[4], msg[5] = id0, id1         //identifier[0] identifier[1]

  72.                 msg[6], msg[7] = gensequence(seq) //sequence[0], sequence[1]


  73.                 length := size + ECHO_REQUEST_HEAD_LEN


  74.                 check := checkSum(msg[0:length])

  75.                 msg[2] = byte(check >> 8)

  76.                 msg[3] = byte(check & 255)


  77.                 conn, err = net.DialTimeout("ip:icmp", host, time.Duration(timeout*1000*1000))


  78.                 checkError(err)


  79.                 starttime = time.Now()

  80.                 conn.SetDeadline(starttime.Add(time.Duration(timeout * 1000 * 1000)))

  81.                 _, err = conn.Write(msg[0:length])


  82.                 const ECHO_REPLY_HEAD_LEN = 20


  83.                 var receive []byte = make([]byte, ECHO_REPLY_HEAD_LEN+length)

  84.                 n, err := conn.Read(receive)

  85.                 _ = n


  86.                 var endduration int = int(int64(time.Since(starttime)) / (1000 * 1000))


  87.                 sumT += endduration


  88.                 time.Sleep(1000 * 1000 * 1000)


  89.                 if err != nil || receive[ECHO_REPLY_HEAD_LEN+4] != msg[4] || receive[ECHO_REPLY_HEAD_LEN+5] != msg[5] || receive[ECHO_REPLY_HEAD_LEN+6] != msg[6] || receive[ECHO_REPLY_HEAD_LEN+7] != msg[7] || endduration >= int(timeout) || receive[ECHO_REPLY_HEAD_LEN] == 11 {

  90.                         lostN++

  91.                         fmt.Println("对 " + cname + "[" + ip.String() + "]" + " 的请求超时。")

  92.                 } else {

  93.                         if shortT == -1 {

  94.                                 shortT = endduration

  95.                         } else if shortT > endduration {

  96.                                 shortT = endduration

  97.                         }

  98.                         if longT == -1 {

  99.                                 longT = endduration

  100.                         } else if longT < endduration {

  101.                                 longT = endduration

  102.                         }

  103.                         recvN++

  104.                         ttl := int(receive[8])

  105.                         //          fmt.Println(ttl)

  106.                         fmt.Println("来自 " + cname + "[" + ip.String() + "]" + " 的回复: 字节=32 时间=" + strconv.Itoa(endduration) + "ms TTL=" + strconv.Itoa(ttl))

  107.                 }


  108.                 seq++

  109.                 count--

  110.         }

  111.         stat(ip.String(), sendN, lostN, recvN, shortT, longT, sumT)

  112.         c <- 1

  113. }


  114. func checkSum(msg []byte) uint16 {

  115.         sum := 0


  116.         length := len(msg)

  117.         for i := 0; i < length-1; i += 2 {

  118.                 sum += int(msg[i])*256 + int(msg[i+1])

  119.         }

  120.         if length%2 == 1 {

  121.                 sum += int(msg[length-1]) * 256 // notice here, why *256?

  122.         }


  123.         sum = (sum >> 16) + (sum & 0xffff)

  124.         sum += (sum >> 16)

  125.         var answer uint16 = uint16(^sum)

  126.         return answer

  127. }


  128. func checkError(err error) {

  129.         if err != nil {

  130.                 fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())

  131.                 os.Exit(1)

  132.         }

  133. }


  134. func gensequence(v int16) (byte, byte) {

  135.         ret1 := byte(v >> 8)

  136.         ret2 := byte(v & 255)

  137.         return ret1, ret2

  138. }


  139. func genidentifier(host string) (byte, byte) {

  140.         return host[0], host[1]

  141. }


  142. func stat(ip string, sendN int, lostN int, recvN int, shortT int, longT int, sumT int) {

  143.         fmt.Println()

  144.         fmt.Println(ip, " 的 Ping 统计信息:")

  145.         fmt.Printf("    数据包: 已发送 = %d,已接收 = %d,丢失 = %d (%d%% 丢失),\n", sendN, recvN, lostN, int(lostN*100/sendN))

  146.         fmt.Println("往返行程的估计时间(以毫秒为单位):")

  147.         if recvN != 0 {

  148.                 fmt.Printf("    最短 = %dms,最长 = %dms,平均 = %dms\n", shortT, longT, sumT/sendN)

  149.         }

  150. }

以上是关于go语言ping实现的主要内容,如果未能解决你的问题,请参考以下文章

go语言连接mysql

go语言连接mysql

go语言学习-配置简单的exporter

go语言实现一个简单的简单网关

Go语言HTTPServer开发的六种实现

Go语言开发(十八)Go语言MySQL数据库操作