From bf9d289c6cc8d9ef6db292096e20f8bc7c876af2 Mon Sep 17 00:00:00 2001 From: YuanEr Date: Wed, 10 Jun 2026 19:41:04 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E5=A4=9A=E4=B8=AAws=20sever=20=E8=B7=AF=E7=94=B1=E6=B1=A1?= =?UTF-8?q?=E6=9F=93=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- znet/server.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/znet/server.go b/znet/server.go index a86bcc4e..52cbe44c 100644 --- a/znet/server.go +++ b/znet/server.go @@ -315,7 +315,8 @@ func (s *Server) ListenTcpConn() { func (s *Server) ListenWebsocketConn() { zlog.Ins().InfoF("[START] WEBSOCKET Server name: %s,listener at IP: %s, Port %d, Path %s is starting", s.Name, s.IP, s.WsPort, s.WsPath) - http.HandleFunc(s.WsPath, func(w http.ResponseWriter, r *http.Request) { + mux := http.NewServeMux() + mux.HandleFunc(s.WsPath, func(w http.ResponseWriter, r *http.Request) { // 1. Check if the server has reached the maximum allowed number of connections // (设置服务器最大连接控制,如果超过最大连接,则等待) if s.ConnMgr.Len() >= zconf.GlobalObject.MaxConn { @@ -358,12 +359,12 @@ func (s *Server) ListenWebsocketConn() { }) if zconf.GlobalObject.CertFile != "" && zconf.GlobalObject.PrivateKeyFile != "" { - err := http.ListenAndServeTLS(fmt.Sprintf("%s:%d", s.IP, s.WsPort), zconf.GlobalObject.CertFile, zconf.GlobalObject.PrivateKeyFile, nil) + err := http.ListenAndServeTLS(fmt.Sprintf("%s:%d", s.IP, s.WsPort), zconf.GlobalObject.CertFile, zconf.GlobalObject.PrivateKeyFile, mux) if err != nil { panic(err) } } else { - err := http.ListenAndServe(fmt.Sprintf("%s:%d", s.IP, s.WsPort), nil) + err := http.ListenAndServe(fmt.Sprintf("%s:%d", s.IP, s.WsPort), mux) if err != nil { panic(err) } From f605aedad895e59ff8a6e601baa760c60c1e69cb Mon Sep 17 00:00:00 2001 From: YuanEr Date: Wed, 10 Jun 2026 19:55:27 +0800 Subject: [PATCH 2/2] =?UTF-8?q?chore:=20=E6=B7=BB=E5=8A=A0zinx=5Fws=5Fmult?= =?UTF-8?q?iserver=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/zinx_ws_multiserver/client/client.go | 52 +++++++++++++++++++ examples/zinx_ws_multiserver/server/server.go | 50 ++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 examples/zinx_ws_multiserver/client/client.go create mode 100644 examples/zinx_ws_multiserver/server/server.go diff --git a/examples/zinx_ws_multiserver/client/client.go b/examples/zinx_ws_multiserver/client/client.go new file mode 100644 index 00000000..0a9df3fd --- /dev/null +++ b/examples/zinx_ws_multiserver/client/client.go @@ -0,0 +1,52 @@ +package main + +import ( + "fmt" + "github.com/aceld/zinx/examples/zinx_client/c_router" + "github.com/aceld/zinx/ziface" + "github.com/aceld/zinx/znet" + "os" + "os/signal" + "syscall" + "time" +) + +func business(connId string, conn ziface.IConnection) { + for i := 0; i < 5; i++ { + err := conn.SendMsg(1, []byte(fmt.Sprintf("ping from %s", connId))) + if err != nil { + fmt.Printf("[%s] send error: %v\n", connId, err) + return + } + time.Sleep(1 * time.Second) + } +} + +func main() { + // Connect to both WebSocket servers to verify they work independently + client1 := znet.NewWsClient("127.0.0.1", 9001) + client2 := znet.NewWsClient("127.0.0.1", 9002) + + client1.AddRouter(2, &c_router.PingRouter{}) + client2.AddRouter(2, &c_router.PingRouter{}) + + client1.SetOnConnStart(func(conn ziface.IConnection) { + go business("client1", conn) + }) + client2.SetOnConnStart(func(conn ziface.IConnection) { + go business("client2", conn) + }) + + client1.Start() + client2.Start() + + fmt.Println("Both clients connected. Press Ctrl+C to exit.") + + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt, syscall.SIGTERM) + <-c + + client1.Stop() + client2.Stop() + fmt.Println("===exit===") +} diff --git a/examples/zinx_ws_multiserver/server/server.go b/examples/zinx_ws_multiserver/server/server.go new file mode 100644 index 00000000..6ff85ecb --- /dev/null +++ b/examples/zinx_ws_multiserver/server/server.go @@ -0,0 +1,50 @@ +package main + +import ( + "fmt" + "github.com/aceld/zinx/examples/zinx_server/s_router" + "github.com/aceld/zinx/zconf" + "github.com/aceld/zinx/znet" + "os" + "os/signal" + "syscall" +) + +func main() { + // Set global mode to websocket-only. + zconf.GlobalObject.Mode = zconf.ServerModeWebsocket + + // Start two WebSocket servers on different ports with the same path "/". + // Before the fix (http.HandleFunc on DefaultServeMux), this would panic: + // http: multiple registrations for / + // After the fix (per-server http.ServeMux), each server handles its own path independently. + servers := []struct { + name string + port int + }{ + {"WsServer-1", 9001}, + {"WsServer-2", 9002}, + } + + for _, s := range servers { + server := znet.NewUserConfServer(&zconf.Config{ + Name: s.name, + Host: "0.0.0.0", + WsPort: s.port, + WsPath: "/", + }) + server.AddRouter(100, &s_router.PingRouter{}) + server.AddRouter(1, &s_router.HelloZinxRouter{}) + go server.Serve() + } + + fmt.Println("Both WebSocket servers started. No route pollution!") + fmt.Println("Server 1: ws://localhost:9001/") + fmt.Println("Server 2: ws://localhost:9002/") + + // Wait for signal to stop + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt, syscall.SIGTERM) + <-c + fmt.Println("===exit===") +}