也可前往本人的个人网站进行阅读
WebSocket和HTTP协议一样,都是基于TCP协议实现的应用层协议。
HTTP协议通常是单边通信,主要用于传输静态文档、请求-响应通信,适用于Web浏览器加载网页、API调用等。然而WebSocket则是会主动给你发消息,实现实时双向通信,我们经常玩的游戏、使用的聊天软件什么采用的都是这个协议。
这里进行详细比较
总的来说,WebSocket和HTTP都是网络通信中的重要协议,但它们在连接性、通信方式和应用场景等方面存在明显的区别。WebSocket更适合实时、双向通信,而HTTP主要用于请求-响应式的通信。
接下来对此协议进行详细讲解,先看图:
首先客户端(client)发送连接请求,通过HTTP发送到服务端,但是请求头会进行一定改变,比如:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
这其中包含了一些特殊的头部,比如 Upgrade
和 Connection
服务器接收到这个请求后,如果支持WebSocket,就会回复一个HTTP 101状态码(切换协议)以及一些额外的头部,表示同意建立WebSocket连接
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
此过程则称为握手,服务端和客户端握手建立连接之后,连接将一直保持,直到其中一方终止
过程中的数据传输:客户端和服务器可以在连接上自由地发送文本或二进制数据帧。这些数据帧包含消息内容以及一些控制信息,如数据帧的类型和长度等
关闭连接:关闭连接时,终止方会发送一个特殊的关闭帧。
以下是一个golang的例子
package main
import (
"log"
"net/http"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
func handleConnections(w http.ResponseWriter, r *http.Request) {
// 将HTTP连接升级为WebSocket连接
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Fatal(err)
return
}
defer conn.Close()
for {
// 读取客户端发送的消息
messageType, p, err := conn.ReadMessage()
if err != nil {
log.Println(err)
return
}
// 将接收到的消息原样发送回客户端
if err := conn.WriteMessage(messageType, p); err != nil {
log.Println(err)
return
}
}
}
func main() {
http.HandleFunc("/ws", handleConnections)
log.Println("WebSocket server is running on :8080")
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal("Error starting server: ", err)
}
}
客户端
package main
import (
"fmt"
"log"
"github.com/gorilla/websocket"
)
func main() {
// 连接WebSocket服务器
conn, _, err := websocket.DefaultDialer.Dial("ws://localhost:8080/ws", nil)
if err != nil {
log.Fatal(err)
}
defer conn.Close()
// 向服务器发送消息
message := []byte("Hello, WebSocket!")
err = conn.WriteMessage(websocket.TextMessage, message)
if err != nil {
log.Fatal(err)
}
// 从服务器接收消息
_, receivedMessage, err := conn.ReadMessage()
if err != nil {
log.Fatal(err)
}
// 打印接收到的消息
fmt.Println("Received message from server:", string(receivedMessage))
}
最后效果: