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===") +} 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) }