【问题标题】:I need solve a problem with websockets on golang server我需要解决 golang 服务器上的 websockets 问题
【发布时间】:2020-11-03 17:31:30
【问题描述】:

我在 GoLang 和 googollee/go-socket.io 上有一个服务器。
当服务端和客户端工作在同一个端口时,sockets正常工作。但是当我开始它们在不同的端口上时,客户端会发生错误:

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)
}

在我的反应应用上

 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();
 }

}

【问题讨论】:

  • 您的问题是“为什么使用错误的端口号时会出现 403 错误?”如果不是,“服务器和客户端工作在不同的端口”是什么意思?
  • 当我在 golang 和客户端分别启动服务器和响应时,出现上述错误
  • 为什么你认为这是一个 CORS 错误?
  • 因为当服务器在运行时提供静态客户端文件(在单个端口上工作),没有错误并且 websockets 工作。也许错误出在其他地方,这只是我的猜测。
  • 从错误消息中可以清楚地看出您有多余的响应。WriteHeader 调用,在指示的行上,与 CORS 完全无关。

标签: reactjs sockets go glide-golang


【解决方案1】:

错误消息表明服务器尝试将您的 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"`
}

因此,将您的信息解组为字符串是行不通的,因为您发送的对象不是字符串,但必须以不同的方式表示。

要解决此问题,您有两种选择:

  1. 更改您的服务器端方法定义以能够接受客户端的数据:

    使用server.OnEvent("/", "msg", func(s socketio.Conn, msg Message) string {,注意msg 现在是Message 类型,这是与接收到的数据匹配的结构。

  1. 更改您的客户端发送的数据:

    使用this.socket.emit("msg", "Hello!"); 仅发送一个字符串(然后将其正确解码为字符串类型的msg 参数。

【讨论】:

  • 非常感谢!这解决了服务器上的问题,但客户端仍然返回错误:“WebSocket connection to 'ws://localhost:4444/socket.io/?EIO=3&transport=websocket&sid=1' failed: Error during WebSocket handshake: Unexpected响应码:403"
  • 我用public socket = openSocket("ws://localhost:4444", {transports: ["polling"]});替换它解决了这个问题
  • @ksksks 感谢您展示示例代码和解决方案!
猜你喜欢
  • 2014-10-24
  • 2010-12-04
  • 2020-12-06
  • 1970-01-01
  • 1970-01-01
  • 2020-08-06
  • 2011-05-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多