【问题标题】:Serving a websocket in Go在 Go 中提供 websocket
【发布时间】:2013-11-11 13:34:51
【问题描述】:

我开始使用 websockets + go 并且我认为我误解了 Go 中 websockets 的一些非常基本的东西。

我想简单地监听一个 websocket 连接并进行相应的处理。但是,我在 Go 中看到的所有使用 websocket 的示例都在为网页提供服务,然后连接到 websocket,这是一个要求吗?

以下是我设置的基本回显服务器:

package main

import (
  "fmt"
  "code.google.com/p/go.net/websocket"
  "net/http"
)

func webHandler(ws *websocket.Conn) {
  var s string
  fmt.Fscan(ws, &s)
  fmt.Println("Received: ", s)
}

func main() {
  fmt.Println("Starting websock server: ")
  http.Handle("/echo", websocket.Handler(webHandler))
  err := http.ListenAndServe(":8080", nil)
  if err != nil {
    panic("ListenAndServe: " + err.Error())
  }
}

这是用于连接的javascript:

ws = new WebSocket("ws://localhost:8080/echo");
ws.onmessage = function(e) {
    console.log("websock: " + e.data);
};

但这会导致: WebSocket 连接到 'ws://localhost:8080/echo' 失败:意外响应代码:403

【问题讨论】:

    标签: websocket go


    【解决方案1】:

    从 Javascript 使用 websocket 时,您很少需要直接读取帧。老实说,我什至不知道该怎么做。

    幸运的是,websocket 包已经有一个类型,Codec 可以为你做这件事。我的建议是使用预定义的 websocket.Message 编解码器来代替 RecieveSend 消息。

    Message 是一个编解码器,用于在 WebSocket 连接的框架中发送/接收文本/二进制数据。要发送/接收文本框,请使用字符串类型。要发送/接收二进制帧,请使用 []byte 类型。

    使用 websocket.Message,你的 webHandler 看起来像这样:

    func webHandler(ws *websocket.Conn) {
        var in []byte
        if err := websocket.Message.Receive(ws, &in); err != nil {
            return
        }
        fmt.Printf("Received: %s\n", string(in))
        websocket.Message.Send(ws, in)      
    }
    

    而且,不,Go 不需要为网页提供服务。您收到的 403 错误与 Go 或 websocket 包无关。

    【讨论】:

    • if 块中的中断是什么意思?
    • @ElgsQianChen 中断很可能是我首先将 Receive 和 Send 放入 for 循环的残余,以防止它在第一条消息后断开连接。我已将其更改为 return
    • 啊,我明白了。感谢@ANisus 的解释。
    【解决方案2】:

    我遇到了类似的问题,403 错误问题与 Go 如何处理 http Origin header 有关:

    Handler 是 WebSocket 浏览器客户端的简单接口。默认情况下,它检查 Origin 标头是否是有效的 URL。您可能想在 func 中验证 websocket.Conn.Config().Origin。如果您使用 Server 而不是 Handler,则可以调用 websocket.Origin 并检查 Handshake func 中的来源。因此,如果您想接受不发送 Origin 标头的非浏览器客户端,则可以使用 Server 。在其握手中不检查来源。

    要禁用 Origin 检查,您必须使用类似:

    http.HandleFunc("/echo",
        func (w http.ResponseWriter, req *http.Request) {
            s := websocket.Server{Handler: websocket.Handler(webHandler)}
            s.ServeHTTP(w, req)
        });
    

    至少这解决了我的问题(服务器到服务器的 WebSocket 通信),我认为如果源头不匹配,它也可以解决问题。

    【讨论】:

    • 我也在寻找一种禁用跨源检查的方法。 src/ondemand/server.go:103:不能在 http.Handle 的参数中使用 func 文字(类型 func(http.ResponseWriter, *http.Request))作为类型 http.Handler:func(http.ResponseWriter, *http.Request ) 没有实现http.Handler(缺少ServeHTTP方法)
    • 该死的,谢谢!这个解决方案不仅有效,而且非常适合我已经拥有的!
    猜你喜欢
    • 1970-01-01
    • 2017-09-21
    • 2016-08-04
    • 1970-01-01
    • 2020-11-23
    • 1970-01-01
    • 2023-03-13
    • 2020-05-10
    • 1970-01-01
    相关资源
    最近更新 更多