WebSocket - 关闭握手大猩猩

时间:2016-02-15 17:49:13

标签: go websocket handshake gorilla

来自WebSocket RFC的

Snippet:

  

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

我正在尝试使用Gorilla WebSocket包使用以下代码执行Close Handshake:

服务器:

// 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:close 1000(normal):woops

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

1 个答案:

答案 0 :(得分:2)

服务器使用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时间旋转。