Kaynağa Gözat

fix reconnect port bind err

dujunchen 1 hafta önce
ebeveyn
işleme
a478177e06

+ 11 - 9
internal/app/stc/broadcast/stc-broadcast.go

@@ -21,17 +21,19 @@ func HandleStcCmd(conn net.Conn) {
 	tmp := make([]byte, 1024)
 
 	for {
-		n, err := conn.Read(tmp)
-		if err != nil {
-			if err != io.EOF {
-				fmt.Println("Error reading from server:", err)
+		if conn != nil {
+			n, err := conn.Read(tmp)
+			if err != nil {
+				if err != io.EOF {
+					fmt.Println("Error reading from server:", err)
+					conn.Close()
+				}
+				return
 			}
-			return
-		}
-
-		// 将新读取的数据追加到缓冲区
-		buf.Write(tmp[:n])
 
+			// 将新读取的数据追加到缓冲区
+			buf.Write(tmp[:n])
+		}
 		// 尝试从缓冲区中提取完整数据包
 		for {
 			packet, err := msgdata.ExtractPacket(&buf)

+ 37 - 28
internal/app/stc/index.go

@@ -8,29 +8,27 @@ import (
 	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
-	ServerAddr := "10.0.11.11"
-	Port := 10100
 
 	for {
 		// 尝试建立连接
-		conn, err := CreateConnection(ServerAddr, Port)
+		conn, err := CreateConnection()
 		if err != nil {
-			fmt.Printf("连接失败 %s:%d,将在5秒后重试...\n", ServerAddr, Port)
-			time.Sleep(5 * time.Second)
-			lfshook.NewLogger().Logger.Infof("reconnect err %+v", err)
+			time.Sleep(2 * time.Second)
 			continue
 		}
-
-		fmt.Printf("成功连接到 %s:%d\n", ServerAddr, Port)
-
+		lfshook.NewLogger().Logger.Infof("Connect success :%s:%d", RemoteAddr, RemotePort)
 		// 启动消息处理和心跳协程
 		wg.Add(2)
 		go func() {
@@ -50,30 +48,38 @@ func StartStcConnection(conn net.Conn) {
 
 		// 等待连接断开
 		wg.Wait()
-		fmt.Println("检测到连接断开,准备重新连接...")
+		fmt.Println("Start Reconnect ...")
 		conn.Close()                // 显式关闭旧连接
 		time.Sleep(time.Second * 1) // 可选:断开后等待1秒再重试
 	}
 }
 
 // 返回错误而不是终止程序
-func CreateConnection(ServerAddr string, Port int) (net.Conn, error) {
-	fmt.Println("========== conn server ==========")
-	conn, err := net.DialTCP("tcp", &net.TCPAddr{
-		IP:   net.ParseIP("0.0.0.0"),
-		Port: 10201,
-	}, &net.TCPAddr{
-		IP:   net.ParseIP(ServerAddr),
-		Port: Port,
-	})
+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
 	}
-	fileDesc, _ := conn.File()
-	fd := fileDesc.Fd()
-	syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
+
 	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()
@@ -88,13 +94,16 @@ func Sendheartbeat(conn net.Conn) {
 			// 编码并发送数据...
 			encoded, err := protocol.Encode()
 			if err != nil {
-				fmt.Printf("编码失败: %v\n", err)
+				fmt.Printf("encode err : %v\n", err)
 				return
 			}
-			_, err = conn.Write(encoded)
-			if err != nil {
-				fmt.Printf("发送心跳失败: %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 // 触发重连
+				}
 			}
 		}
 	}

+ 2 - 1
internal/app/stc/sendstatus/status.go

@@ -13,8 +13,9 @@ func SendToStc(conn net.Conn, data []byte) {
 	_, err := conn.Write(data)
 	if err != nil {
 		fmt.Println("send msg err:", err)
+		conn.Close()
 	}
-	lfshook.NewLogger().Logger.Infof("=data:==%x", data)
+	lfshook.NewLogger().Logger.Infof("====data:==%x", data)
 }
 
 // report alarm status to STC