如何在 Golang 中正确关闭 WebSocket 连接

在用 Golang 开发 WebSocket 客户端时,我遇到了因连接关闭不当而导致的重复错误信息。要解决这些问题,了解关闭 WebSocket 连接的正确方法至关重要,我将在本篇文章中与大家分享。

——作者:Sean Zheng

设置 WebSocket 客户端

首先,让我们定义 WebSocket 客户端的基本结构和设置:

定义客户端结构

const defaultWebSocketClientEndpoint = "wss://api.fugle.tw/marketdata/v1.0/stock/streaming"  

type WebSocketClientOption struct {  
    Endpoint string `json:"endpoint"`  
    APIKey   string `json:"apiKey"`  
}  
type WebSocketClient struct {  
    Conn   *websocket.Conn  
    option WebSocketClientOption  
}

WebSocket 客户端构造函数

func NewWebSocketClient(option WebSocketClientOption) (*WebSocketClient, error) {  
    if option.Endpoint == "" {  
        option.Endpoint = defaultWebSocketClientEndpoint  
    }  
    return &WebSocketClient{  
        Conn:   nil,  
        option: option,  
    }, nil  
}

建立和关闭连接

正确处理 WebSocket 连接需要了解突然关闭 TCP 连接与有序关闭 WebSocket 连接之间的区别。

连接到 WebSocket

func (client *WebSocketClient) Connect() error {  
    conn, resp, err := websocket.DefaultDialer.Dial(client.option.Endpoint, nil)  
    if err != nil {  
        return err  
    }  
    defer resp.Body.Close()  
    client.Conn = conn  
    return nil  
}

正确的 WebSocket 关闭说明

Conn.Close() 与发送关闭消息的区别

1. Conn.Close() 方法:

  • 该方法是 net.Conn 接口的一部分,用于直接关闭 TCP 连接。它会立即终止底层 TCP 连接,而不管任何正在进行的数据传输。
  • 使用 Conn.Close()可能会导致对等程序接收到不完整的数据,因为它没有遵循 WebSocket 协议来结束连接。这可能会导致对端收到一个 TCP RST(重置)数据包,表明连接突然终止。
  • 它通常用于出错或需要立即断开连接,而不考虑从容完成数据交换的情况。

2. 发送关闭消息

  • 在 WebSocket 协议中,关闭消息是一种特殊的控制消息,用于表示端点希望关闭连接。这是一个有序、优雅的关闭过程,允许对等方发送相应的关闭消息作为回应。
  • 发送关闭消息后,应用程序通常会继续接收数据,直到收到对等方的关闭消息。这样可确保双方都有机会完成任何待处理的数据交换,遵守 WebSockets 的正常终止流程。
  • 这是正确断开 WebSocket 连接的推荐方法,因为它符合 WebSocket 协议,能确保数据完整性和连接的正确终止。

关闭功能实现

func  (client *WebSocketClient) Close() error {  
     // 发送 WebSocket 关闭消息
    Deadline := time.Now().Add(time.Minute)  
    err := client.Conn.WriteControl(  
        websocket.CloseMessage,  
        websocket.FormatCloseMessage( websocket.CloseNormalClosure, "" ),  
        Deadline,  
    )  
     if err != nil {  
         return err  
    }  

     // 设置读取下一条消息的截止时间
    err = client.Conn.SetReadDeadline(time.Now().Add( 5 * time.Second ))  
     if err != nil {  
         return err  
    }  
     // 读取消息,直到确认关闭消息
    for {  
        _, _, err = client.Conn.NextReader()  
         if websocket.IsCloseError(err, websocket.CloseNormalClosure) {  
             break  
         }  
         if err != nil {  
             break  
         }  
    }  
     // 关闭 TCP 连接
    err = client.Conn.Close()  
     if err != nil {  
         return err  
    }  
     return  nil  
 }

结论

通过遵守概述的技术,您可以确保干净利落地终止 WebSocket 连接,而不会出现任何残余错误。这将提高应用程序的稳定性,并通过保持干净高效的通信通道来增强整体用户体验。

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。

(0)

相关推荐

发表回复

登录后才能评论