這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
ICMP是用來對網路狀況進行反饋的協議,可以用來偵測網路狀態或檢測網路錯誤。
限於當前Golang在網路編程方面的代碼稀缺,資料甚少,所以分享一個用Golang來構造ICMP資料包並發送ping程式的echo訊息的執行個體。
RFC792定義的echo資料包結構:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type | Code | Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Identifier | Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Data ... +-+-+-+-+-
代碼:
package mainimport ("bytes""encoding/binary""fmt""net")type ICMP struct {Type uint8Code uint8Checksum uint16Identifier uint16SequenceNum uint16}func CheckSum(data []byte) uint16 {var (sum uint32length int = len(data)index int)for length > 1 {sum += uint32(data[index])<<8 + uint32(data[index+1])index += 2length -= 2}if length > 0 {sum += uint32(data[index])}sum += (sum >> 16)return uint16(^sum)}func main() {var (icmp ICMPladdr net.IPAddr = net.IPAddr{IP: net.ParseIP("192.168.137.111")} //***IP地址改成你自己的網段***raddr net.IPAddr = net.IPAddr{IP: net.ParseIP("192.168.137.1")})//如果你要使用網路層的其他協議還可以設定成 ip:ospf、ip:arp 等conn, err := net.DialIP("ip4:icmp", &laddr, &raddr)if err != nil {fmt.Println(err.Error())return}defer conn.Close()//開始填充資料包icmp.Type = 8 //8->echo message 0->reply messageicmp.Code = 0icmp.Checksum = 0icmp.Identifier = 0icmp.SequenceNum = 0var (buffer bytes.Buffer)//先在buffer中寫入icmp資料報求去校正和binary.Write(&buffer, binary.BigEndian, icmp)icmp.Checksum = CheckSum(buffer.Bytes())//然後清空buffer並把求完校正和的icmp資料報寫入其中準備發送buffer.Reset()binary.Write(&buffer, binary.BigEndian, icmp)if _, err := conn.Write(buffer.Bytes()); err != nil {fmt.Println(err.Error())return}fmt.Printf("send icmp packet success!")}
執行後可以用wireshark抓下包看看,可以看到遠方網關傳來了reply響應:
看看我們構造的ICMP是否正確:
如果轉載請註明出處:http://blog.csdn.net/gophers/article/details/21481447