go语言ping实现

package main import ( "flag" "fmt" "net" "os" "strconv" "time" ) func main() { var count int var timeout int64 var size int var neverstop bool flag.Int64Var(&timeout, "w", 1000, "等待每次回复的超时时间(毫秒)。") flag.IntVar(&count, "n", 4, "要发送的回显请求数。") flag.IntVar(&size, "l", 32, "要发送缓冲区大小。") flag.BoolVar(&neverstop, "t", true, "Ping 指定的主机,直到停止。") flag.Parse() args := flag.Args() if len(args) < 1 { fmt.Println("Usage: ", os.Args[0], "host") flag.PrintDefaults() flag.Usage() os.Exit(1) } ch := make(chan int) argsmap := map[string]interface{}{} argsmap["w"] = timeout argsmap["n"] = count argsmap["l"] = size argsmap["t"] = neverstop for _, host := range args { go ping(host, ch, argsmap) } for i := 0; i < len(args); i++ { <-ch } os.Exit(0) } func ping(host string, c chan int, args map[string]interface{}) { var count int var size int var timeout int64 var neverstop bool count = args["n"].(int) size = args["l"].(int) timeout = args["w"].(int64) neverstop = args["t"].(bool) cname, _ := net.LookupCNAME(host) starttime := time.Now() conn, err := net.DialTimeout("ip4:icmp", host, time.Duration(timeout*1000*1000)) ip := conn.RemoteAddr() fmt.Println("正在 Ping " + cname + " [" + ip.String() + "] 具有 32 字节的数据:") var seq int16 = 1 id0, id1 := genidentifier(host) const ECHO_REQUEST_HEAD_LEN = 8 sendN := 0 recvN := 0 lostN := 0 shortT := -1 longT := -1 sumT := 0 for count > 0 || neverstop { sendN++ var msg []byte = make([]byte, size+ECHO_REQUEST_HEAD_LEN) msg[0] = 8 // echo msg[1] = 0 // code 0 msg[2] = 0 // checksum msg[3] = 0 // checksum msg[4], msg[5] = id0, id1 //identifier[0] identifier[1] msg[6], msg[7] = gensequence(seq) //sequence[0], sequence[1] length := size + ECHO_REQUEST_HEAD_LEN check := checkSum(msg[0:length]) msg[2] = byte(check >> 8) msg[3] = byte(check & 255) conn, err = net.DialTimeout("ip:icmp", host, time.Duration(timeout*1000*1000)) checkError(err) starttime = time.Now() conn.SetDeadline(starttime.Add(time.Duration(timeout * 1000 * 1000))) _, err = conn.Write(msg[0:length]) const ECHO_REPLY_HEAD_LEN = 20 var receive []byte = make([]byte, ECHO_REPLY_HEAD_LEN+length) n, err := conn.Read(receive) _ = n var endduration int = int(int64(time.Since(starttime)) / (1000 * 1000)) sumT += endduration time.Sleep(1000 * 1000 * 1000) 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 { lostN++ fmt.Println("对 " + cname + "[" + ip.String() + "]" + " 的请求超时。") } else { if shortT == -1 { shortT = endduration } else if shortT > endduration { shortT = endduration } if longT == -1 { longT = endduration } else if longT < endduration { longT = endduration } recvN++ ttl := int(receive[8]) // fmt.Println(ttl) fmt.Println("来自 " + cname + "[" + ip.String() + "]" + " 的回复: 字节=32 时间=" + strconv.Itoa(endduration) + "ms TTL=" + strconv.Itoa(ttl)) } seq++ count-- } stat(ip.String(), sendN, lostN, recvN, shortT, longT, sumT) c <- 1 } func checkSum(msg []byte) uint16 { sum := 0 length := len(msg) for i := 0; i < length-1; i += 2 { sum += int(msg[i])*256 + int(msg[i+1]) } if length%2 == 1 { sum += int(msg[length-1]) * 256 // notice here, why *256? } sum = (sum >> 16) + (sum & 0xffff) sum += (sum >> 16) var answer uint16 = uint16(^sum) return answer } func checkError(err error) { if err != nil { fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error()) os.Exit(1) } } func gensequence(v int16) (byte, byte) { ret1 := byte(v >> 8) ret2 := byte(v & 255) return ret1, ret2 } func genidentifier(host string) (byte, byte) { return host[0], host[1] } func stat(ip string, sendN int, lostN int, recvN int, shortT int, longT int, sumT int) { fmt.Println() fmt.Println(ip, " 的 Ping 统计信息:") fmt.Printf(" 数据包: 已发送 = %d,已接收 = %d,丢失 = %d (%d%% 丢失),\n", sendN, recvN, lostN, int(lostN*100/sendN)) fmt.Println("往返行程的估计时间(以毫秒为单位):") if recvN != 0 { fmt.Printf(" 最短 = %dms,最长 = %dms,平均 = %dms\n", shortT, longT, sumT/sendN) } }

原文发布于微信公众号 - Golang语言社区(Golangweb)

原文发表时间:2017-09-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏转载gongluck的CSDN博客

FFmpeg菜鸡互啄#第3篇#视频解码

解码过程 ? 基本过程:打开输入文件,查找视频流,打开解码器,循环读帧解码帧,关闭解码器,关闭输入文件。 解码数据结构 ? Code #define _C...

4028
来自专栏小灰灰

Java 借助ImageMagic实现图片编辑服务

Java 借助ImageMagic实现图片编辑服务 java原生对于图片的编辑处理并没有特别友好,而且问题也有不少,那么作为一个java后端,如果要提供图片的编...

8306
来自专栏机器学习算法与Python学习

Python:matplotlib

原文链接:http://blog.csdn.net/ywjun0919/article/details/8692018 来源于书籍:《Python科学计算》 ...

4148
来自专栏跟着阿笨一起玩NET

C# 使用 NPOI 库读写 Excel 文件

NPOI 是开源的 POI 项目的.NET版,可以用来读写Excel,Word,PPT文件。在处理Excel文件上,NPOI 可以同时兼容 xls 和 xlsx...

6051
来自专栏我和未来有约会

silverlight项目小结

最近又用silverlight做了一个小的东西,如图: ? 主要就是下边的导航,点击了后上边的大图和文字简介都跟着做相应的变化。 界面设计的思路:整个silve...

3906
来自专栏JackieZheng

可视化工具solo show-----Prefuse自带例子GraphView讲解

  2014.10.15日以来的一个月,挤破了头、跑断了腿、伤透了心、吃够了全国最大餐饮连锁店——沙县小吃。其中酸甜苦辣,绝不是三言两语能够说得清道的明的。校招...

5046
来自专栏nimomeng的自我进阶

抓住iOS的未来 - 30天学习编写30个Swift小程序

=======================================================

4852
来自专栏技术总结

YYImage框架瞧一瞧

建议查看原文:https://www.jianshu.com/p/83edaeeb5851(不定时更新)

1533
来自专栏CDA数据分析师

36条常用Excel技巧 收藏备用!

1、两列数据查找相同值对应的位置 =MATCH(B1,A:A,0) 2、已知公式得结果 定义名称=EVALUATE(Sheet1!C1) 已知结果得公式 定义名...

2135
来自专栏图形学与OpenGL

实验8 OpenGL交互

(1) 运行示范实验代码1,掌握程序鼠标交互方法,尝试为其添加键盘与菜单控制,实现同样功能;

1932

扫码关注云+社区

领取腾讯云代金券