要基于 net/http
库编写一个简单的 WebSocket 回显服务器,您需要:
- 发起握手
- 从客户端接收数据帧
- 向客户端发送数据帧
- 关闭握手
首先,让我们创建一个带有 WebSocket 端点的 HTTP 处理程序:
// HTTP server with WebSocket endpoint
func Server() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
ws, err := NewHandler(w, r)
if err != nil {
// handle error
}
if err = ws.Handshake(); err != nil {
// handle error
}
…
然后初始化WebSocket结构。
初始握手请求始终来自客户端。一旦服务器定义了 WebSocket 请求,它需要用握手响应进行回复。
请记住,您不能使用 http.ResponseWriter 编写响应,因为一旦您开始发送响应,它将关闭底层 TCP 连接。
所以你需要使用HTTP劫持。劫持允许您接管底层 TCP 连接处理程序和 bufio.Writer。这使您可以在不关闭 TCP 连接的情况下读取和写入数据。
// NewHandler initializes a new handler
func NewHandler(w http.ResponseWriter, req *http.Request) (*WS, error) {
hj, ok := w.(http.Hijacker)
if !ok {
// handle error
} .....
}
要完成握手,服务器必须使用适当的标头进行响应。
// Handshake creates a handshake header
func (ws *WS) Handshake() error {
hash := func(key string) string {
h := sha1.New()
h.Write([]byte(key))
h.Write([]byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}(ws.header.Get("Sec-WebSocket-Key"))
.....
}
“Sec-WebSocket-key”是随机生成的,是 Base64 编码的。服务器在接受请求后需要将此密钥附加到固定字符串。假设您有 x3JJHMbDL1EzLkh9GBhXDw== 密钥。在这种情况下,您可以使用 SHA-1 计算二进制值并使用 Base64 对其进行编码。你会得到 HSmrc0sMlYUkAGmm5OPpG2HaGWk=。将此用作 Sec-WebSocket-Accept 响应标头的值。
标签:http,err,应用程序,ws,func,error,Go,WebSocket From: https://blog.51cto.com/yuzhou1su/6363133