理解HTTP如何升级为WebSocket需要了解一些协议层面的细节。WebSocket是基于HTTP协议的一个扩展,它允许客户端和服务器之间进行全双工通信。以下是详细的升级过程原理:
升级过程原理
-
HTTP请求握手:
WebSocket连接始于一个HTTP请求,它包含特殊的头部字段,这些字段请求服务器升级连接到WebSocket协议。 -
客户端发送升级请求:
客户端发送一个HTTP GET请求到服务器,并在请求头中包含以下字段:Upgrade: websocket
:表示请求升级到WebSocket协议。Connection: Upgrade
:表示客户端希望升级连接。Sec-WebSocket-Key
:一个Base64编码的随机字符串,用于服务器生成响应。Sec-WebSocket-Version
:WebSocket协议版本,一般为13
。
示例请求:
GET /chat HTTP/1.1 Host: example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Version: 13
-
服务器处理升级请求:
服务器收到升级请求后,检查请求头以确保它们包含正确的值。如果请求有效,服务器生成一个响应以完成升级。服务器生成
Sec-WebSocket-Accept
值:- 取
Sec-WebSocket-Key
的值。 - 连接一个固定的字符串
258EAFA5-E914-47DA-95CA-C5AB0DC85B11
。 - 对连接后的字符串进行SHA-1哈希计算。
- 对哈希结果进行Base64编码。
- 取
-
服务器响应升级请求:
服务器发送一个HTTP 101响应,表示协议切换,并在响应头中包含以下字段:Upgrade: websocket
:确认协议升级。Connection: Upgrade
:确认协议升级。Sec-WebSocket-Accept
:包含服务器生成的接受密钥。
示例响应:
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
-
建立WebSocket连接:
一旦服务器发送HTTP 101响应,连接正式升级为WebSocket协议,客户端和服务器可以开始通过WebSocket进行全双工通信。
代码实现示例
以下是一个简单的Go示例,展示如何实现HTTP到WebSocket的升级:
package main
import (
"log"
"net/http"
"sync"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true // 允许所有来源
},
}
var connections = make([]*websocket.Conn, 0)
var mu sync.Mutex
func handleConnections(w http.ResponseWriter, r *http.Request) {
// 升级HTTP连接到WebSocket连接
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Fatal(err)
}
defer ws.Close()
mu.Lock()
connections = append(connections, ws)
mu.Unlock()
for {
// 读取消息
messageType, message, err := ws.ReadMessage()
if err != nil {
log.Println(err)
break
}
// 广播消息给所有连接
mu.Lock()
for _, conn := range connections {
if conn != ws {
if err := conn.WriteMessage(messageType, message); err != nil {
log.Println(err)
}
}
}
mu.Unlock()
}
}
func main() {
http.HandleFunc("/ws", handleConnections)
log.Println("服务器启动在 :8080")
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
结论
WebSocket连接的升级过程通过HTTP请求握手完成。客户端发起一个带有特定头部的HTTP GET请求,服务器验证请求并响应协议切换,最终建立WebSocket连接。这一过程允许在客户端和服务器之间建立低延迟、全双工的通信通道。