WebSocket - 关闭握手 Gorilla

Posted

技术标签:

【中文标题】WebSocket - 关闭握手 Gorilla【英文标题】:WebSocket - Closing Handshake Gorilla 【发布时间】:2016-02-15 17:49:12 【问题描述】:

来自 WebSocket RFC 的片段:

使用状态码(第 7.4 节)/code/ 和可选的关闭原因(第 7.1.6 节)/reason/ 启动 WebSocket 关闭握手,端点必须发送关闭控制帧,如 5.5.1 节所述,其状态码设置为 /code/,其关闭原因设置为 /reason/。一旦端点发送和接收了关闭控制帧,该端点应该关闭 WebSocket 连接,如第 7.1.1 节中定义的那样。

我正在尝试使用带有以下代码的 Gorilla WebSocket 包进行关闭握手:

服务器:

// Create upgrader function
conn, err := upgrader.Upgrade(w, r, nil)

// If there is an error stop everything.
if err != nil 
    fmt.Println(err)
    return


for 
    // Read Messages
    _, _, err := conn.ReadMessage()
    // Client is programmed to send a close frame immediately...
    // When reading close frame resend close frame with same
    // reason and code
    conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(1000, "woops"))
    fmt.Println(err)
    break

客户:

d := &websocket.Dialer

conn, _, err := d.Dial("ws://localhost:8080", nil)

if err != nil 
    fmt.Println(err)
    return


go func() 
    for 
        // Read Messages
        _, _, err := conn.ReadMessage()

        if c, k := err.(*websocket.CloseError); k 
            if(c.Code == 1000) 
                // Never entering since c.Code == 1005
                fmt.Println(err)
                break
            
        
    
()

conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(1000, "woops"))

for 

服务器正在按预期读取关闭帧,输出以下内容:

websocket:关闭 1000(正常):呜呜呜

但是,客户端就像它在发送关闭消息后停止阅读一样。 ReadMessage 继续返回错误 1005。我做错了什么?

【问题讨论】:

【参考方案1】:

服务器用code响应关闭帧:

    c.WriteControl(CloseMessage, []byte, time.Now().Add(writeWait))

这被客户端转换为关闭代码 1005(未收到状态)。

客户端应用程序看不到服务器写入的 1000 oops 关闭帧,因为 websocket 连接在收到第一个关闭帧后停止从网络读取。

当 ReadMessage 返回错误时,客户端应用程序应退出循环。无需检查特定的关闭代码。

for 
    // Read Messages
    _, _, err := conn.ReadMessage()
    if err != nil 
        break
    

与问题中的问题无关,服务器应用程序应该在发送关闭帧后close websocket 连接。

同样与问题中的问题无关,使用select 而不是for 来阻塞主goroutine。前者只是阻塞了 goroutine。后者使用 CPU 时间旋转。

【讨论】:

我知道这个答案很旧,但这似乎是错误的:“使用select 而不是for 。前者永远阻塞。后者永远旋转。” OP没有从chans中读取。这就是 select 的用途。 conn.ReadMessage() 已被阻止。 @ArturSapek 该评论是指在 OP 的代码末尾使用 for for 构造会消耗 CPU 时间。 select 将简单地阻止。对 conn.ReadMessage() 的调用不会阻塞主 goroutine。

以上是关于WebSocket - 关闭握手 Gorilla的主要内容,如果未能解决你的问题,请参考以下文章

rxjs/webSocket - 到“ws://localhost:3000/”的 WebSocket 连接失败:连接在收到握手响应之前关闭

Websocket 握手仅在 IE 10 中立即关闭

与“ws://localhost:3000/”的 WebSocket 连接失败:在收到握手响应之前连接已关闭

WebSocket - 关闭框架

Socket.io - 失败:连接在收到握手响应之前关闭

使用 Python 服务器的 Websocket 握手问题