从零开始学golang之ping

freedbg · · 1128 次点击 · 开始浏览    置顶
这是一个创建于 的主题,其中的信息可能已经有所发展或是发生改变。

```go package main import ( "errors" "fmt" "net" "os" // "runtime" // "sync" //"testing" "time" "./xnet/xnternal/iana" //use of internal package not allowed "./xnet/xnternal/nettest" "golang.org/x/net/icmp" "golang.org/x/net/ipv4" "golang.org/x/net/ipv6" ) //-ldflags=-linkmode=internal func main() { //使用go get 安装x/net 不能成功 // planB: git clone git@github.com:golang/net.git $GOPATH./src/golang.org/x/net/ //这是golang net test 代码用来学习 删除ip6 的支持数据 if m, ok := nettest.SupportsRawIPSocket(); !ok { fmt.Println(m) return } else { fmt.Println(m, ok) } for i, tt := range privilegedPingTests { fmt.Println(i, tt) if err := doPing(tt, i); err != nil { fmt.Println(err) return } } } func googleAddr(c *icmp.PacketConn, protocol int) (net.Addr, error) { const host = "www.baidu.com" ips, err := net.LookupIP(host) if err != nil { return nil, err } fmt.Println(ips) netaddr := func(ip net.IP) (net.Addr, error) { switch c.LocalAddr().(type) { case *net.UDPAddr: return &net.UDPAddr{IP: ip}, nil case *net.IPAddr: return &net.IPAddr{IP: ip}, nil default: return nil, errors.New("neither UDPAddr nor IPAddr") } } for _, ip := range ips { switch protocol { case iana.ProtocolICMP: fmt.Println("ICMP") fmt.Println(ip.To4()) //os.Exit(1) if ip.To4() != nil { return netaddr(ip) } case iana.ProtocolIPv6ICMP: if ip.To16() != nil && ip.To4() == nil { return netaddr(ip) } } } return nil, errors.New("no A or AAAA record") } type pingTest struct { network, address string protocol int //协议 mtype icmp.Type //协议类型 } var privilegedPingTests = []pingTest{ {"ip4:icmp", "0.0.0.0", iana.ProtocolICMP, ipv4.ICMPTypeEcho}, //{"ip6:ipv6-icmp", "::", iana.ProtocolIPv6ICMP, ipv6.ICMPTypeEchoRequest}, } func doPing(tt pingTest, seq int) error { //net.ListenPacket(network, address) c, err := icmp.ListenPacket(tt.network, tt.address) if err != nil { return err } defer c.Close() dst, err := googleAddr(c, tt.protocol) if err != nil { return err } fmt.Println(dst) // if tt.network != "udp6" && tt.protocol == iana.ProtocolIPv6ICMP { // var f ipv6.ICMPFilter // f.SetAll(true) // f.Accept(ipv6.ICMPTypeDestinationUnreachable) // f.Accept(ipv6.ICMPTypePacketTooBig) // f.Accept(ipv6.ICMPTypeTimeExceeded) // f.Accept(ipv6.ICMPTypeParameterProblem) // f.Accept(ipv6.ICMPTypeEchoReply) // if err := c.IPv6PacketConn().SetICMPFilter(&f); err != nil { // return err // } // } wm := icmp.Message{ Type: tt.mtype, Code: 0, Body: &icmp.Echo{ ID: os.Getpid() & 0xffff, Seq: 1 << uint(seq), Data: []byte("HELLO-R-U-THERE"), }, } //返回校验和消息 wb, err := wm.Marshal(nil) if err != nil { return err } fmt.Println(wm.Body) if n, err := c.WriteTo(wb, dst); err != nil { return err } else if n != len(wb) { return fmt.Errorf("got %v; want %v", n, len(wb)) } rb := make([]byte, 1500) if err := c.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil { return err } n, peer, err := c.ReadFrom(rb) if err != nil { return err } rm, err := icmp.ParseMessage(tt.protocol, rb[:n]) if err != nil { return err } fmt.Printf("read from %v\n", peer) //获取我们发送出去的数据 在这里可以写入时间来计算往返时间 dd, err := rm.Body.Marshal(iana.ProtocolICMP) //fmt.Println(icmp.Echo(rm.Body)) fmt.Printf("%s\n", dd[4:]) /** * 或者使用unsafe 转换 * t := T { A: 10, B: "abc", } l := unsafe.Sizeof(t) pb := (*[1024]byte)(unsafe.Pointer(&t)) fmt.Println("Struct:", t) fmt.Println("Bytes:", (*pb)[:l]) * * * */ switch rm.Type { case ipv4.ICMPTypeEchoReply, ipv6.ICMPTypeEchoReply: return nil default: return fmt.Errorf("got %+v from %v; want echo reply", rm, peer) } } ``` 代码有点粗糙,将就着看吧 https://github.com/godla/TCP-IP-Study.git

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1128 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传