package stc import ( "fmt" "net" "pbx-api-gin/internal/app/ami/action" "pbx-api-gin/internal/app/stc/broadcast" msgdata "pbx-api-gin/internal/app/stc/data" "pbx-api-gin/pkg/lfshook" "sync" "syscall" "time" ) const RemotePort = 10100 const LocalPort = 10201 const RemoteAddr = "10.0.11.11" func StartStcConnection(conn net.Conn) { //var conn net.Conn var wg sync.WaitGroup for { // 尝试建立连接 conn, err := CreateConnection() if err != nil { time.Sleep(2 * time.Second) continue } lfshook.NewLogger().Logger.Infof("Connect success :%s:%d", RemoteAddr, RemotePort) // 启动消息处理和心跳协程 wg.Add(2) go func() { defer wg.Done() broadcast.HandleStcCmd(conn) // 处理消息 }() go func() { defer wg.Done() Sendheartbeat(conn) // 发送心跳 }() //start AMI go action.StartAMI(func() { lfshook.NewLogger().Info("ami callback") // 首次连接才进行初始化 }, []func(event map[string]string){}, conn) // 等待连接断开 wg.Wait() fmt.Println("Start Reconnect ...") conn.Close() // 显式关闭旧连接 time.Sleep(time.Second * 1) // 可选:断开后等待1秒再重试 } } // 返回错误而不是终止程序 func CreateConnection() (net.Conn, error) { lfshook.NewLogger().Logger.Infof("========Connect server IP:%s :Port:%d", RemoteAddr, RemotePort) // 创建 Dialer dialer := &net.Dialer{ LocalAddr: &net.TCPAddr{IP: net.ParseIP("0.0.0.0"), Port: LocalPort}, // 固定本地端口 Control: controlTCPConn, } DialAddr := fmt.Sprintf("%s:%d", RemoteAddr, RemotePort) conn, err := dialer.Dial("tcp", DialAddr) if err != nil { lfshook.NewLogger().Logger.Infof("========Connect server err :%+v", err) return nil, err } return conn, nil } func controlTCPConn(network, address string, c syscall.RawConn) error { return c.Control(func(fd uintptr) { syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) // 注意:SO_REUSEPORT 在某些系统可用(如 Linux),但非标准 }) } func Sendheartbeat(conn net.Conn) { var count uint8 protocol := msgdata.NewProtocol() // 初始化协议... ticker := time.NewTicker(2 * time.Second) defer ticker.Stop() for { select { case <-ticker.C: count++ // 编码并发送数据... encoded, err := protocol.Encode() if err != nil { fmt.Printf("encode err : %v\n", err) return } if conn != nil { _, err = conn.Write(encoded) if err != nil { fmt.Printf("Send hearbeat err: %v\n", err) conn.Close() return // 触发重连 } } } } } // 检查PA server是主状态还是从状态 func CheckMaster(conn net.Conn) bool { // var count uint8 //init heartbeat data protocol := msgdata.NewProtocol() protocol.SourceID = 0x02 protocol.DestinationID = 0x01 protocol.MessageID = 0x21 protocol.DataLength = 0x04 return false }