zoukankan      html  css  js  c++  java
  • 用Golang自己构造ICMP数据包

    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 ...
       +-+-+-+-+-

    代码:

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. package main  
    2.   
    3. import (  
    4.     "bytes"  
    5.     "encoding/binary"  
    6.     "fmt"  
    7.     "net"  
    8. )  
    9.   
    10. type ICMP struct {  
    11.     Type        uint8  
    12.     Code        uint8  
    13.     Checksum    uint16  
    14.     Identifier  uint16  
    15.     SequenceNum uint16  
    16. }  
    17.   
    18. func CheckSum(data []byte) uint16 {  
    19.     var (  
    20.         sum    uint32  
    21.         length int = len(data)  
    22.         index  int  
    23.     )  
    24.     for length > 1 {  
    25.         sum += uint32(data[index])<<8 + uint32(data[index+1])  
    26.         index += 2  
    27.         length -= 2  
    28.     }  
    29.     if length > 0 {  
    30.         sum += uint32(data[index])  
    31.     }  
    32.     sum += (sum >> 16)  
    33.   
    34.     return uint16(^sum)  
    35. }  
    36.   
    37. func main() {  
    38.     var (  
    39.         icmp  ICMP  
    40.         laddr net.IPAddr = net.IPAddr{IP: net.ParseIP("192.168.137.111")}  //***IP地址改成你自己的网段***  
    41.         raddr net.IPAddr = net.IPAddr{IP: net.ParseIP("192.168.137.1")}  
    42.     )  
    43.     //如果你要使用网络层的其他协议还可以设置成 ip:ospf、ip:arp 等  
    44.     conn, err := net.DialIP("ip4:icmp", &laddr, &raddr)  
    45.     if err != nil {  
    46.         fmt.Println(err.Error())  
    47.         return  
    48.     }  
    49.     defer conn.Close()  
    50.   
    51.     //开始填充数据包  
    52.     icmp.Type = //8->echo message  0->reply message  
    53.     icmp.Code = 0  
    54.     icmp.Checksum = 0  
    55.     icmp.Identifier = 0  
    56.     icmp.SequenceNum = 0  
    57.   
    58.     var (  
    59.         buffer bytes.Buffer  
    60.     )  
    61.     //先在buffer中写入icmp数据报求去校验和  
    62.     binary.Write(&buffer, binary.BigEndian, icmp)  
    63.     icmp.Checksum = CheckSum(buffer.Bytes())  
    64.     //然后清空buffer并把求完校验和的icmp数据报写入其中准备发送  
    65.     buffer.Reset()  
    66.     binary.Write(&buffer, binary.BigEndian, icmp)  
    67.   
    68.     if _, err := conn.Write(buffer.Bytes()); err != nil {  
    69.         fmt.Println(err.Error())  
    70.         return  
    71.     }  
    72.     fmt.Printf("send icmp packet success!")  
    73. }  


    执行后可以用wireshark抓下包看看,可以看到远方网关传来了reply响应:

    看看我们构造的ICMP是否正确:

    如果转载请注明出处:http://blog.csdn.NET/gophers/article/details/21481447

  • 相关阅读:
    Animation
    Calendar
    ToggleButton
    ASP.NET备份恢复SqlServer数据库
    ConfirmButton
    DropDown
    备份与恢复ACCESS数据库
    PopupControl
    CascadingDropDown
    RoundedCorners
  • 原文地址:https://www.cnblogs.com/php-rearch/p/5962855.html
Copyright © 2011-2022 走看看