好的,我来给你做一份 WebSocket 详解,从概念、原理、协议、优缺点,到使用方法和示例都覆盖,方便你理解和应用。
1. WebSocket 是什么
WebSocket 是一种 在单个 TCP 连接上进行全双工通信的协议,由 HTML5 引入。它可以让客户端和服务器之间进行 实时双向数据传输,比传统 HTTP 更高效。
特点:
- 双向通信:客户端和服务器可以随时互相发送消息。
- 长连接:一次握手后保持连接,不需要每次请求都重新建立。
- 低延迟:减少 HTTP 请求头开销,实时性强。
- 轻量数据传输:消息帧小,适合实时应用。
2. WebSocket 与 HTTP 的区别
特性 | HTTP | WebSocket |
---|---|---|
通信方式 | 单向请求/响应 | 双向通信 |
连接状态 | 短连接,每次请求建立 | 长连接,握手一次 |
实时性 | 较低 | 高 |
数据传输效率 | 需要频繁发送请求头 | 消息帧小,开销低 |
适用场景 | 普通网页访问 | 聊天、游戏、股票行情、物联网 |
3. WebSocket 工作原理
3.1 建立连接
- 客户端发起 HTTP 升级请求(Upgrade):
GET /chat HTTP/1.1 Host: server.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Version: 13
- 服务器响应升级成功:
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
3.2 数据传输
- 连接建立后,客户端和服务器通过 消息帧(Frame) 发送数据。
- WebSocket 支持 文本(UTF-8) 和 二进制数据。
- 数据帧格式简单,开销低,实时性高。
3.3 关闭连接
- 任意一方都可以发送 关闭帧(Close Frame)关闭连接。
- 关闭时可带上状态码和原因。
4. WebSocket 协议细节
4.1 消息类型
类型 | 描述 |
---|---|
Text | 文本消息 |
Binary | 二进制消息 |
Close | 关闭连接 |
Ping | 心跳检测 |
Pong | 心跳响应 |
4.2 消息帧结构
WebSocket 帧包含:
- FIN:是否为最后一帧
- Opcode:操作码(如文本、二进制)
- Mask:是否掩码(客户端必须对数据掩码)
- Payload Length:负载长度
- Payload Data:实际数据
5. WebSocket 优缺点
优点
- 双向通信,实时性强
- 长连接,减少握手开销
- 支持二进制数据
- 开发简单,可用 JavaScript 直接在浏览器中使用
缺点
- 需要浏览器或客户端支持
- 防火墙或代理可能阻塞 WebSocket
- 长连接占用资源
- 不适合传统请求/响应场景
6. WebSocket 使用示例
6.1 浏览器端(JavaScript)
// 创建 WebSocket 连接
const ws = new WebSocket("ws://localhost:8080/ws");
// 连接打开
ws.onopen = () => {
console.log("Connected");
ws.send("Hello Server!");
};
// 接收消息
ws.onmessage = (event) => {
console.log("Received:", event.data);
};
// 关闭连接
ws.onclose = () => {
console.log("Disconnected");
};
// 发生错误
ws.onerror = (err) => {
console.error("Error:", err);
};
6.2 Go 语言服务器端
使用 github.com/gorilla/websocket
包:
package main
import (
"fmt"
"net/http"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{}
func wsHandler(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
fmt.Println("Upgrade error:", err)
return
}
defer conn.Close()
for {
mt, message, err := conn.ReadMessage()
if err != nil {
fmt.Println("Read error:", err)
break
}
fmt.Printf("Received: %s\n", message)
err = conn.WriteMessage(mt, message)
if err != nil {
fmt.Println("Write error:", err)
break
}
}
}
func main() {
http.HandleFunc("/ws", wsHandler)
fmt.Println("Server started at :8080")
http.ListenAndServe(":8080", nil)
}
- 功能:接收客户端消息并回显(Echo)。
7. WebSocket 应用场景
- 即时聊天系统:微信、Slack、聊天室
- 实时推送:股票行情、新闻推送
- 多人在线游戏
- 物联网设备通信
- 协作编辑:在线文档、白板
发表回复