我需要解决 golang 服务器上的 websockets 问题
I need solve a problem with websockets on golang server
我在 GoLang 和 googollee/go-socket.io
上有一个服务器。
当服务器端和客户端工作在同一个端口时,套接字工作正常。但是当我启动它们时,它们在不同的端口上,客户端发生错误:
WebSocket connection to 'ws://localhost:4444/socket.io/?EIO=3&transport=websocket&sid=6' failed: Error during WebSocket handshake: Unexpected response code: 403
POST http://localhost:4444/socket.io/?EIO=3&transport=polling&t=NDDzcYM&sid=5 400 (Bad Request)
GET http://localhost:4444/socket.io/?EIO=3&transport=polling&t=NDDzcYC&sid=5 400 (Bad Request)
WebSocket connection to 'ws://localhost:4444/socket.io/?EIO=3&transport=websocket&sid=5' failed: Error during WebSocket handshake: Unexpected response code: 403
在服务器上:
connected: 1 closed client namespace disconnect meet error: json: cannot unmarshal object into Go value of type string connected: 2
这是我的代码:
package main
import (
"fmt"
"log"
"net/http"
"github.com/gorilla/mux"
"github.com/rs/cors"
socketio "github.com/googollee/go-socket.io"
)
func main() {
fmt.Println("Hello world")
router := mux.NewRouter()
router.HandleFunc("/is-alive", isAlive).Methods("GET")
server, err := socketio.NewServer(nil)
if err != nil {
log.Fatal(err)
}
server.OnConnect("/", func(s socketio.Conn) error {
s.SetContext("")
fmt.Println("connected:", s.ID())
s.Emit("change")
s.Join("bcast")
return nil
})
server.OnEvent("/", "msg", func(s socketio.Conn, msg string) string {
s.SetContext(msg)
s.Emit("change")
fmt.Println("event: msg")
return "recv " + msg
})
server.OnError("/", func(s socketio.Conn, e error) {
fmt.Println("meet error:", e)
})
server.OnDisconnect("/", func(s socketio.Conn, reason string) {
fmt.Println("closed", reason)
})
go server.Serve()
defer server.Close()
router.Handle("/socket.io/", server)
c := cors.New(cors.Options{
AllowedOrigins: []string{"http://localhost:3000"},
AllowCredentials: true,
})
handler := c.Handler(router)
log.Println("Serving at localhost:4444...")
log.Fatal(http.ListenAndServe(":4444", handler))
}
func isAlive(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}
在我的 React 应用程序上
import socketIOClient from "socket.io-client";
export class SocketClientManager {
public socket = socketIOClient("ws://localhost:4444");
public subscribe() {
this.socket.emit("msg", { msg: "Hello!" });
}
public setCallback(callback: (arg: any) => void) {
this.socket.on("change", callback);
}
public async unsubscribe() {
this.socket.disconnect();
}
}
错误消息表明服务器试图将您的 JSON 对象解组为字符串,但它期望的是不同的东西。
原因在您的方法定义中:
server.OnEvent("/", "msg", func(s socketio.Conn, msg string) string {
msg
是字符串类型。
但是,您发送了一条不同类型的消息:
public subscribe() {
this.socket.emit("msg", { msg: "Hello!" });
}
这条消息可以在这个结构定义中描述:
type Message struct {
Msg string `json:"msg"`
}
所以将您的信息解组为字符串是行不通的,因为您发送的对象不是字符串,但必须以不同的方式表示。
要解决此问题,您有两种选择:
更改您的服务器端方法定义以能够接受客户端的数据:
使用server.OnEvent("/", "msg", func(s socketio.Conn, msg Message) string {
,注意msg
现在是Message
类型,这是与接收到的数据相匹配的结构。
或
更改您的客户端发送的数据:
使用 this.socket.emit("msg", "Hello!");
仅发送一个字符串(然后将其正确解码为字符串类型的 msg
参数。
我在 GoLang 和 googollee/go-socket.io
上有一个服务器。
当服务器端和客户端工作在同一个端口时,套接字工作正常。但是当我启动它们时,它们在不同的端口上,客户端发生错误:
WebSocket connection to 'ws://localhost:4444/socket.io/?EIO=3&transport=websocket&sid=6' failed: Error during WebSocket handshake: Unexpected response code: 403
POST http://localhost:4444/socket.io/?EIO=3&transport=polling&t=NDDzcYM&sid=5 400 (Bad Request)
GET http://localhost:4444/socket.io/?EIO=3&transport=polling&t=NDDzcYC&sid=5 400 (Bad Request)
WebSocket connection to 'ws://localhost:4444/socket.io/?EIO=3&transport=websocket&sid=5' failed: Error during WebSocket handshake: Unexpected response code: 403
在服务器上:
connected: 1 closed client namespace disconnect meet error: json: cannot unmarshal object into Go value of type string connected: 2
这是我的代码:
package main
import (
"fmt"
"log"
"net/http"
"github.com/gorilla/mux"
"github.com/rs/cors"
socketio "github.com/googollee/go-socket.io"
)
func main() {
fmt.Println("Hello world")
router := mux.NewRouter()
router.HandleFunc("/is-alive", isAlive).Methods("GET")
server, err := socketio.NewServer(nil)
if err != nil {
log.Fatal(err)
}
server.OnConnect("/", func(s socketio.Conn) error {
s.SetContext("")
fmt.Println("connected:", s.ID())
s.Emit("change")
s.Join("bcast")
return nil
})
server.OnEvent("/", "msg", func(s socketio.Conn, msg string) string {
s.SetContext(msg)
s.Emit("change")
fmt.Println("event: msg")
return "recv " + msg
})
server.OnError("/", func(s socketio.Conn, e error) {
fmt.Println("meet error:", e)
})
server.OnDisconnect("/", func(s socketio.Conn, reason string) {
fmt.Println("closed", reason)
})
go server.Serve()
defer server.Close()
router.Handle("/socket.io/", server)
c := cors.New(cors.Options{
AllowedOrigins: []string{"http://localhost:3000"},
AllowCredentials: true,
})
handler := c.Handler(router)
log.Println("Serving at localhost:4444...")
log.Fatal(http.ListenAndServe(":4444", handler))
}
func isAlive(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}
在我的 React 应用程序上
import socketIOClient from "socket.io-client";
export class SocketClientManager {
public socket = socketIOClient("ws://localhost:4444");
public subscribe() {
this.socket.emit("msg", { msg: "Hello!" });
}
public setCallback(callback: (arg: any) => void) {
this.socket.on("change", callback);
}
public async unsubscribe() {
this.socket.disconnect();
}
}
错误消息表明服务器试图将您的 JSON 对象解组为字符串,但它期望的是不同的东西。
原因在您的方法定义中:
server.OnEvent("/", "msg", func(s socketio.Conn, msg string) string {
msg
是字符串类型。
但是,您发送了一条不同类型的消息:
public subscribe() {
this.socket.emit("msg", { msg: "Hello!" });
}
这条消息可以在这个结构定义中描述:
type Message struct {
Msg string `json:"msg"`
}
所以将您的信息解组为字符串是行不通的,因为您发送的对象不是字符串,但必须以不同的方式表示。
要解决此问题,您有两种选择:
更改您的服务器端方法定义以能够接受客户端的数据:
使用
server.OnEvent("/", "msg", func(s socketio.Conn, msg Message) string {
,注意msg
现在是Message
类型,这是与接收到的数据相匹配的结构。
或
更改您的客户端发送的数据:
使用
this.socket.emit("msg", "Hello!");
仅发送一个字符串(然后将其正确解码为字符串类型的msg
参数。