介绍
小编给大家分享一下golang利用原始套接字构造UDP包的示例,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获、下面让我们一起去了解一下吧!
<强>原始套接字介绍强>
TCP/IP协议中,最常见的就是原始(SOCKET_RAW), TCP (SOCKET_STREAM), UDP (SOCKET_DGRA)三种套接字。原始套接字能够对底层传输进行控制,允许自行组装数据包,比如修改本地IP,发送Ping包,进行网络监听。这里不做详细介绍,要了解更多可以网上自己查询。
<强>实现
强>
这里先看IP头结构:
其中16位总长度包括IP头长度和数据的长度,8位协议填写17日,因为UDP协议类型为17。这里要说明一下IP头中的首部校验,这个值只校验IP头部,不包含数据。
这里给出校验算法,IP头和UDP头中使用的校验算法是一样的。
func 校验和(msg []字节),uint16 { ,sum :=0 ,for n :=, 1;, n & lt;, len(味精)1;,n +=, 2, { sum 才能+=,int(味精[n]) * 256, +, int(味精(n + 1)) ,}=,sum (sum 在祝辞,16),+,(sum ,, 0 xffff) ,sum +=, (sum 在祝辞,16) ,var ans =, uint16(^总和) return 答 }
下面开始填充IP头,这里使用了golang.org/x/net下的ipv4包
,//目的IP ,dst :=, net.IPv4 (192,, 168,, 1,, 2)//源IP ,src :=, net.IPv4 (192,, 168,, 1,, 3) ,//填充ip首部 ,iph :=,, ipv4.Header { ,,版本:ipv4.Version,//IP头才能长一般是20 Len:,,才能ipv4.HeaderLen, 服务条款才能:,,0 x00,//迷才能为数据 TotalLen才能:ipv4.HeaderLen +, len(浅黄色), TTL才能:,,64年, 国旗:才能,ipv4.DontFragment, ,,FragOff: 0, 协议:才能,17日 校验和才能:0, Src才能:,,Src, Dst才能:,,Dst, ,} , ,h, err :=, iph.Marshal () ,if err  !=, nil { log.Fatalln才能(err) ,} ,//计算IP头部校验值 ,iph.Checksum =, int(校验和(h))
下面开始处理UDP头部,先来看UDP头结构:
UDP头结构就很简单了,16位UDP校验和涉及到一个UDP伪首部的东西,我们先来看下UDP伪首部的构成。
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |,,,32 bit Source IP address | ----------------------------------------- |,,,32 bit Destination IP addr | ----------------------------------------- | 0 |还以为;8 bit 原型|,16 bit header 长度| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
伪首部包含了源IP、目的IP,协议号,16位的长度。这个伪首部仅仅参与校验计算。
下面开始填充UDP头:
,//填充UDP首部 ,//udp伪首部 ,udph :=,([]字节,,20) ,//源ip地址 ,udph [0], udph [1],, udph [2],, udph [3],=, src [12],, src [13],,, src src [14], [15] ,//目的ip地址 ,udph [4], udph [5],, udph [6],, udph [7],=, dst.IP [12],, dst.IP [13],, dst.IP [14],, dst.IP [15] ,//协议类型 ,udph [8], udph [9],=, 0 x00, 0 x11 ,//udp头长度 ,udph [10], udph[11],=,,,字节0 x00 (len(浅黄色)+ 8) ,//下面开始就真正的udp头部 ,//源端口号 ,udph [12], udph [13],=, 0 x27 0 x10 ,//目的端口号 ,udph [14], udph [15],=, 0 x17, 0 x70 ,//udp头长度 ,udph [16], udph[17],=,,,字节0 x00 (len(浅黄色)+ 8) ,//校验和 ,udph [18], udph [19],=, 0 x00, 0 x00 ,//计算校验值 ,check :=,校验和(附加(udph,迷……) ,udph [18], udph[19],=,字节(check>在8和255),,字节(check& 255)
下面我们需要发送自己构造的UDP包,可以使用净下的ListenPacket。
,侦听器,err :=, net.ListenPacket (“ip4: udp",,“192.168.1.104") ,if err  !=, nil { log.Fatal才能(err) ,} ,defer listener.Close () , ,//listener 实现了net.PacketConn接口 ,r, err :=, ipv4.NewRawConn (c) ,if err  !=, nil { log.Fatal才能(err) ,} ,//发送自己构造的UDP包 ,if err =, r.WriteTo (iph,附加(udph[12:20],迷…),,nil);, err !=, nil { log.Fatal才能(err) 以前,}golang利用原始套接字构造UDP包的示例