rts-sim-testing-service/third_party/udp/udp_server.go

88 lines
1.7 KiB
Go
Raw Normal View History

package udp
import (
"context"
"log/slog"
"net"
2023-10-19 14:02:20 +08:00
"runtime/debug"
)
type UdpServer interface {
2024-01-24 13:25:00 +08:00
Listen() error
Close()
}
type UdpMsgHandler func(b []byte)
type server struct {
addr string
conn *net.UDPConn
handler UdpMsgHandler
cancelFn context.CancelFunc
2024-01-24 13:25:00 +08:00
done chan struct{} // 服务协程退出信号
}
// NewServer creates a new instance of UdpServer.
func NewServer(addr string, handler UdpMsgHandler) UdpServer {
2024-01-24 13:25:00 +08:00
return &server{addr: addr, handler: handler, done: make(chan struct{})}
}
2024-01-24 13:25:00 +08:00
func (s *server) Listen() error {
udpAddr, err := net.ResolveUDPAddr("udp", s.addr)
if err != nil {
2024-01-24 13:25:00 +08:00
return err
}
conn, err := net.ListenUDP("udp", udpAddr)
if err != nil {
2024-01-24 13:25:00 +08:00
return err
}
s.conn = conn
ctx, cfn := context.WithCancel(context.Background())
// 启动监听处理
go s.listenAndHandle(ctx)
s.cancelFn = cfn
2024-01-24 13:25:00 +08:00
return nil
}
func (s *server) Close() {
2024-01-24 13:25:00 +08:00
err := s.conn.Close()
if err != nil {
slog.Error("udp server close error", "error", err)
}
s.cancelFn()
2024-01-24 13:25:00 +08:00
<-s.done
}
func (s *server) listenAndHandle(ctx context.Context) {
2024-01-24 13:25:00 +08:00
defer close(s.done)
defer s.conn.Close()
2024-01-24 13:25:00 +08:00
mainLoop:
for {
select {
case <-ctx.Done():
2024-01-24 13:25:00 +08:00
// slog.Info("udp server listen 关闭", "addr", s.addr)
break mainLoop
default:
}
buf := make([]byte, 1024)
n, _, err := s.conn.ReadFromUDP(buf)
if err != nil {
slog.Error("udp server read error", "addr", s.addr, "error", err)
continue
}
// slog.Debug("udp server handle", "addr", ap.String())
go s.handle(buf[:n])
}
}
func (s *server) handle(b []byte) {
defer func() {
if err := recover(); err != nil {
2023-10-19 14:02:20 +08:00
slog.Error("udp server handle error", "error", err, "stack", string(debug.Stack()))
debug.PrintStack()
}
}()
// slog.Info("udp server handle", "msg", string(b))
s.handler(b)
}