为了账号安全,请及时绑定邮箱和手机立即绑定

Sec-Websocket-协议问题

Sec-Websocket-协议问题

Go
人到中年有点甜 2023-07-31 15:08:41
我在使用 WebSockets 协议时遇到 Go 问题。如果我连接到我的 API,一切都会正常。如果我添加“协议”,例如“Hey”,它会开始循环多次,并以错误结束*github.com/gorilla/websocket.CloseError:“Code 1006,Text Unexpected EOF”。Sec-Websocket-Protocol我绝对不明白为什么当我在连接中发送时它会这样。有我的代码:main.gopackage mainimport (    "fmt"    "github.com/golang/glog"    "github.com/grpc-ecosystem/grpc-gateway/runtime"    stacktracer "gitlab.com/eyes-eyes/internals-stacktracer"    "gitlab.com/eyesbank/go-web-sockets-server/handlers"    "net/http")const webSocketsAddr = "0.0.0.0:8082"// main is the starting point of the current micro service.func main() {    // Setting the service name    stacktracer.SetServiceName("Hello 'X' (Web Sockets)")    // Initializing the HTTP errors handling    runtime.HTTPError = stacktracer.DefaultHTTPError    if err := RunWebSocketsServer(); err != nil {        glog.Fatal(err)    }}//// WebSocket//func RunWebSocketsServer() error {    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {        handlers.HandleUserSocket(w, r)    })    fmt.Println(webSocketsAddr)    return http.ListenAndServe(webSocketsAddr, nil)}func RunWebSocketsTLSServer() error {    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {        handlers.HandleUserSocket(w, r)    })    fmt.Println(webSocketsAddr)    return http.ListenAndServeTLS(webSocketsAddr, "server.crt", "server.key", nil)}
查看完整描述

1 回答

?
阿波罗的战车

TA贡献1862条经验 获得超6个赞

如果客户端请求子协议并且服务器不同意这些子协议之一,则客户端需要关闭连接。客户端使用 Sec-Websocket-Protocol 标头来请求一个或多个子协议。服务器使用 Sec-Websocket-Protocol 响应标头来同意协议。有关此主题的更多信息,请参阅RFC 。


通过同意客户端请求的协议之一来解决问题。有几种方法可以做到这一点。


第一种是使用内置的协议协商功能:


var upgrader = websocket.Upgrader{

    ReadBufferSize:  1024,

    WriteBufferSize: 1024,

    Subprotocols: []string{ "hey" },  // <-- add this line

    CheckOrigin: func(r *http.Request) bool {

        return true

    },

}

第二种是在调用 Upgrade 之前在应用程序代码中协商协议。调用websocket.Subprotocols获取请求的协议,选择其中一种协议并在升级的标头参数中指定该协议。


h := http.Header{}

for _, sub := range websocket.Subprotocols(req) {

   if sub == "hey" {

      h.Set("Sec-Websocket-Protocol", "hey")

      break

   }

}

conn, err := upgrader.Upgrade(w, r, h)

除了这个问题之外,应用程序应该defer conn.Close()在成功升级后。


此外,还可以简化错误处理逻辑。应用程序应在从 ReadMessage 返回任何错误时退出读取循环。连接错误后写入消息是没有意义的。ReadMessage 方法在成功时返回非零消息。


for {

    // Read message from browser

    _, msg, err := conn.ReadMessage()

    if err != nil {

         fmt.Println(err.Error())

          fmt.Println("disconnected")

          return

    }

    WriteOutgoingMessage(conn, userID.Hex() + " " + string(msg))

}

           


查看完整回答
反对 回复 2023-07-31
  • 1 回答
  • 0 关注
  • 92 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信