```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
有疑问加站长微信联系(非本文作者)