1 Star 0 Fork 0

leonxiong/xtool

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
udpbroadcast.go 4.32 KB
一键复制 编辑 原始数据 按行查看 历史
leonxiong 提交于 2024-12-08 10:50 +08:00 . update xtool
package udpbroadcast
import (
"encoding/json"
"fmt"
"gitee.com/xlm516/xtool/dbg"
xid "gitee.com/xlm516/xtool/id"
xnet "gitee.com/xlm516/xtool/net"
"gitee.com/xlm516/xtool/sys"
xtime "gitee.com/xlm516/xtool/time"
"net"
"strings"
"sync"
"time"
)
type BroadcastMsg struct {
Action string
Response int
FromGUID string
ToGUID string
Session string
Seq int64
Time int64
Argument interface{}
}
type BroadcastCtrl struct {
bindPort int
remotePort int
conn net.PacketConn
uuid string
sessionMap sync.Map
reqChanMap sync.Map
connSend []*net.UDPConn
Handler func(ctrl *BroadcastCtrl, pkt *BroadcastMsg, addr net.Addr)
}
type WaitChanInfo struct {
ch chan *BroadcastMsg
Session string
Time int64
}
func NewBroadcastCtrl(bindPort int, remotePort int) *BroadcastCtrl {
resp := new(BroadcastCtrl)
resp.bindPort = bindPort
resp.remotePort = remotePort
resp.init()
return resp
}
func (me *BroadcastCtrl) init() {
me.uuid = xid.NewGUID()
me.connSend = make([]*net.UDPConn, 0)
}
func (me *BroadcastCtrl) Start() error {
macIP, _ := xnet.GetMacIP()
remoteAddr, _ := net.ResolveUDPAddr("udp", fmt.Sprintf("255.255.255.255:%d", me.remotePort))
for _, v := range macIP {
for _, v2 := range v.IPS {
if strings.IndexByte(v2.IP, ':') > 0 {
continue
}
localAdd, _ := net.ResolveUDPAddr("udp", v2.IP+":0")
tmpConn, err := net.DialUDP("udp", localAdd, remoteAddr)
if err != nil {
continue
}
fmt.Println("bind udp:", v2.IP, "ok")
me.connSend = append(me.connSend, tmpConn)
}
}
tmpConn, err := net.ListenPacket("udp", fmt.Sprintf(":%d", me.bindPort))
if err != nil {
dbg.Dbg("Error: %s\n", err.Error())
return err
}
me.conn = tmpConn
go me.loopRead()
go me.checkSession()
return nil
}
func (me *BroadcastCtrl) checkSession() {
for {
nowTime := xtime.UnixTime()
me.sessionMap.Range(func(key, value interface{}) bool {
t, ok := value.(int64)
if ok {
if xtime.CompTime(nowTime, t) >= 10 {
me.sessionMap.Delete(key)
}
}
return true
})
me.reqChanMap.Range(func(key, value interface{}) bool {
chInfo, ok := value.(*WaitChanInfo)
if ok {
if xtime.CompTime(nowTime, chInfo.Time) <= 8 {
me.closeCh(chInfo.ch)
me.reqChanMap.Delete(key)
}
}
return true
})
time.Sleep(time.Second * 5)
}
}
func (me *BroadcastCtrl) closeCh(ch chan *BroadcastMsg) {
defer sys.RecoverFunc("", 0)
if ch != nil {
close(ch)
}
}
func (me *BroadcastCtrl) loopRead() {
buf := make([]byte, 10000)
for {
n, addr, err := me.conn.ReadFrom(buf)
if err != nil {
dbg.Dbg("Error: ", err)
time.Sleep(time.Second * 10)
continue
}
if n > 0 {
me.processData(buf[:n], addr)
}
}
}
func (me *BroadcastCtrl) processData(data []byte, addr net.Addr) {
pkt := new(BroadcastMsg)
err := json.Unmarshal(data, pkt)
if err != nil {
dbg.Dbg("Error: %s\n", err.Error())
dbg.Dbg("Msg: %s\n", string(data))
return
}
if pkt.FromGUID == me.uuid {
return
}
_, ok := me.sessionMap.Load(pkt.Session)
if ok {
return
}
me.sessionMap.Store(pkt.Session, xtime.UnixTime())
inf, ok := me.reqChanMap.Load(pkt.Session)
if ok {
me.reqChanMap.Delete(pkt.Session)
chInfo, ok := inf.(*WaitChanInfo)
if ok {
chInfo.ch <- pkt
me.closeCh(chInfo.ch)
}
}
if me.Handler != nil {
me.Handler(me, pkt, addr)
}
}
func (me *BroadcastCtrl) SendRequest(action string, data interface{}, wait bool) *BroadcastMsg {
msg := new(BroadcastMsg)
msg.Action = action
msg.Response = 0
msg.FromGUID = me.uuid
msg.Session = xid.NewGUID()
msg.Argument = data
b, _ := json.MarshalIndent(msg, "", " ")
var chanInfo *WaitChanInfo
if wait {
chanInfo = new(WaitChanInfo)
chanInfo.ch = make(chan *BroadcastMsg, 1)
chanInfo.Session = msg.Session
chanInfo.Time = xtime.UnixTime()
me.reqChanMap.Store(chanInfo.Session, chanInfo)
}
for _, v := range me.connSend {
_, _ = v.Write(b)
}
if wait {
select {
case msg := <-chanInfo.ch:
return msg
case <-time.After(time.Second * 5):
break
}
return nil
} else {
return nil
}
}
func (me *BroadcastCtrl) SendResponse(msg *BroadcastMsg, data interface{}) error {
msg.Response = 1
msg.ToGUID = msg.FromGUID
msg.FromGUID = me.uuid
if sys.IsNil(data) == false {
msg.Argument = data
}
b, _ := json.MarshalIndent(msg, "", " ")
for _, v := range me.connSend {
_, _ = v.Write(b)
}
return nil
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/xlm516/xtool.git
git@gitee.com:xlm516/xtool.git
xlm516
xtool
xtool
2929073dc254

搜索帮助