Open alpha-baby opened 3 years ago
下列代码是我copy的 Ping 那个demo然后做了一些修改而成
Ping
这代码我在本地的mac上跑是有问题的, 但是在linux上跑就是正确的:
mac 系统版本为 1.15.5 go 版本为 1.13.8 和 1.15.5 都试过
原文在: https://github.com/astaxie/NPWG_zh/blob/master/zh/Text/chapter-socket.html 的最底部
package basic import ( "fmt" "net" "os" "time" "encoding/hex" ) func Ping() { if len(os.Args) != 2 { fmt.Println("Usage: ", os.Args[0], "host") os.Exit(1) } addr, err := net.ResolveIPAddr("ip", os.Args[1]) if err != nil { fmt.Println("Resolution error", err.Error()) os.Exit(1) } var localAddr *net.IPAddr if localAddr == nil { conn, err := net.Dial("tcp", "www.baidu.com:80") checkError(err) localAddr, err = net.ResolveIPAddr("ip4", conn.LocalAddr().(*net.TCPAddr).IP.String()) checkError(err) } conn, err := net.DialIP("ip4:icmp", localAddr, addr) checkError(err) var msg [512]byte msg[0] = 8 // echo msg[1] = 0 // code 0 msg[2] = 0 // checksum, fix later msg[3] = 0 // checksum, fix later msg[4] = 0 // identifier[0] msg[5] = 13 //identifier[1] msg[6] = 0 // sequence[0] msg[7] = 37 // sequence[1] length := 8 check := CheckSum(msg[0:length]) msg[2] = byte(check >> 8) msg[3] = byte(check & 255) startTime := time.Now() _, err = conn.Write(msg[0:length]) checkError(err) n, err := conn.Read(msg[0:]) checkError(err) fmt.Printf("raw ip msg: %v \n", hex.EncodeToString(msg[:n])) endTime := time.Now() result := make([]byte, n) if n > 20 { result = msg[20:] } fmt.Println("Got response") if result[5] == 13 { fmt.Println("identifier matches") } if result[7] == 37 { fmt.Println("Sequence matches") } fmt.Println("ip packet: ", msg[:n], "length: ", n) ipHeadLength := int(msg[0]) & 15 * 4 fmt.Printf("ip header length: %v \n", ipHeadLength) fmt.Printf("ip len %x %x \n", msg[2], msg[3]) // 重点在这里,我发现在mac系统上,我用wirshark 抓包抓到的数据和这里读到的数据是不一样的 totalLength := int(msg[2])<<8 + int(msg[3]) fmt.Printf("ip total length: %v \n", totalLength) ipDataLength := totalLength - ipHeadLength fmt.Println("icmp packet: ", result[:ipDataLength]) t := endTime.Sub(startTime) fmt.Printf("time: %.3f ms\n", float64(t.Microseconds())/1000) } // 原文中的计算校验和的代码是有问题的,这里我换成了另外的,这个函数是没有问题的 func CheckSum(data []byte) uint16 { var ( sum uint32 length int = len(data) index int ) //以每16位为单位进行求和,直到所有的字节全部求完或者只剩下一个8位字节(如果剩余一个8位字节说明字节数为奇数个) for length > 1 { sum += uint32(data[index])<<8 + uint32(data[index+1]) index += 2 length -= 2 } //如果字节数为奇数个,要加上最后剩下的那个8位字节 if length > 0 { sum += uint32(data[index]) } //加上高16位进位的部分 sum += (sum >> 16) //别忘了返回的时候先求反 return uint16(^sum) }
这是代码获取到的IP 报文的结果:
=== RUN TestPing host: [103.235.46.39] raw ip msg: 4500080038c700002f01103e279c454f0a01cbf00000ffcd000d0025 Got response identifier matches Sequence matches ip packet: [69 0 8 0 56 199 0 0 47 1 16 62 39 156 69 79 10 1 203 240 0 0 255 205 0 13 0 37] length: 28 ip header length: 20 ip len 8 0 ip total length: 2048 --- FAIL: TestPing (0.36s) panic: runtime error: slice bounds out of range [:2028] with capacity 492 [recovered] panic: runtime error: slice bounds out of range [:2028] with capacity 492
用wirshark 抓到的包: IP包 起始位置为第一行的: 45 00
0000 00 e0 4c 6b 10 e0 3c f5 cc 71 88 01 08 00 45 00 0010 00 1c 38 c7 00 00 2f 01 10 3e 27 9c 45 4f 0a 01 0020 cb f0 00 00 ff cd 00 0d 00 25 00 00 00 00 00 00 0030 00 00 00 00 00 00 00 00 00 00 00 00
sudo
下列代码是我copy的
Ping
那个demo然后做了一些修改而成这代码我在本地的mac上跑是有问题的, 但是在linux上跑就是正确的:
mac 系统版本为 1.15.5 go 版本为 1.13.8 和 1.15.5 都试过
原文在: https://github.com/astaxie/NPWG_zh/blob/master/zh/Text/chapter-socket.html 的最底部
这是代码获取到的IP 报文的结果:
用wirshark 抓到的包: IP包 起始位置为第一行的: 45 00
这是不是go的一个bug??