|
@@ -0,0 +1,93 @@
|
|
|
+package commonutil
|
|
|
+
|
|
|
+import (
|
|
|
+ "bytes"
|
|
|
+ "encoding/binary"
|
|
|
+ "net"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+//
|
|
|
+type UdpClient struct {
|
|
|
+ Local string
|
|
|
+ Connect *net.UDPConn
|
|
|
+ BufSize int
|
|
|
+}
|
|
|
+
|
|
|
+//指令
|
|
|
+const (
|
|
|
+ OP_NOOP = byte(iota)
|
|
|
+ OP_JOIN
|
|
|
+ OP_BYE
|
|
|
+ OP_SAY_ONLINE
|
|
|
+ OP_TYPE_DATA
|
|
|
+ OP_GET_DOWNLOADERCODE //上报下载器代码
|
|
|
+ OP_WILLCHANGEIP //将要切换IP
|
|
|
+ OP_PUSH_DOWNLOADERCODES //
|
|
|
+ OP_DELETE_DOWNLOADERCODES //需要删除
|
|
|
+ OP_NEWCLIENT //下载器重新链接
|
|
|
+)
|
|
|
+
|
|
|
+//
|
|
|
+func (c *UdpClient) Listen(fn func(byte, []byte, *net.UDPAddr)) {
|
|
|
+ listenAddr, _ := net.ResolveUDPAddr("udp4", c.Local)
|
|
|
+ c.Connect, _ = net.ListenUDP("udp4", listenAddr)
|
|
|
+ go c.readUdp(fn)
|
|
|
+}
|
|
|
+
|
|
|
+//写
|
|
|
+func (c *UdpClient) WriteUdp(data []byte /*写入数据*/, act byte /*动作*/, toaddr *net.UDPAddr /*目标端地址*/) error {
|
|
|
+ bs := make([]byte, 1)
|
|
|
+ bs[0] = act
|
|
|
+ sizebs := Int2Byte(int32(len(data)))
|
|
|
+ bs = append(bs, sizebs...)
|
|
|
+ bs = append(bs, data...)
|
|
|
+ if len(bs) > c.BufSize {
|
|
|
+ bs = bs[:c.BufSize]
|
|
|
+ } else if len(bs) < c.BufSize {
|
|
|
+ bs = append(bs, bytes.Repeat([]byte{0}, c.BufSize-len(bs))...)
|
|
|
+ }
|
|
|
+ for i := 0; i < 5; i++ { //尝试5次
|
|
|
+ _, err := c.Connect.WriteToUDP(bs, toaddr)
|
|
|
+ if err == nil {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ time.Sleep(1 * time.Second)
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+//读
|
|
|
+func (c *UdpClient) readUdp(fn func(byte, []byte, *net.UDPAddr)) {
|
|
|
+ for {
|
|
|
+ head := make([]byte, c.BufSize)
|
|
|
+ n, ra, err := c.Connect.ReadFromUDP(head)
|
|
|
+ if err != nil || n == 0 { //取不到数据
|
|
|
+ time.Sleep(1 * time.Second)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ size := int(Byte2Int(head[1:5]))
|
|
|
+ if size < 1 { //无数据,仅仅是控制指令
|
|
|
+ go fn(head[0], []byte{}, ra)
|
|
|
+ } else {
|
|
|
+ if size > c.BufSize-5 {
|
|
|
+ size = c.BufSize - 5
|
|
|
+ }
|
|
|
+ go fn(head[0], head[5:5+size], ra)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+func Byte2Int(src []byte) int32 {
|
|
|
+ var ret int32
|
|
|
+ binary.Read(bytes.NewReader(src), binary.BigEndian, &ret)
|
|
|
+ return ret
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+func Int2Byte(src int32) []byte {
|
|
|
+ buf := bytes.NewBuffer([]byte{})
|
|
|
+ binary.Write(buf, binary.BigEndian, src)
|
|
|
+ return buf.Bytes()
|
|
|
+}
|