package util import ( "bytes" "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_SEND_EMAIL //发送邮件 ) // 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) } } }