Gin集成WebSocket
概述
Gin
框架下使用WebSocket通讯协议与Web前端(Vue2)通讯的简易实现。WebSocket
是一种网络通讯协议,它允许在客户端和服务器之间进行全双工通信。与传统的HTTP
请求不同,WebSocket
提供了一种双向通信机制,服务器可以主动向客户端推送信息,而客户端也可以随时发送信息给服务器;由于WebSocket建立在一个长连接上,它比频繁建立新连接的HTTP轮询更高效和节能,因此WebSocket的实时性非常适合做需要实时数据交换的应用,如在线游戏,聊天应用等。思路
websocket
客户端和服务端都是怎么连接上的,以及它们是怎么保持连接的?websocket的连接步骤
-
1. 握手阶段。客户端会先发起
Websocket
连接时,发送一个HTTP
请求到服务器到服务器。服务器收到请求后会进行一系列验证,包括检查协议版本、Origin、Sec-WebSocket-Key等。如果验证通过则返回HTTP 101
状态码,表示成功切换到WebSocket
协议。 -
2. 保持连接。WebSocket连接建立后,客户端和服务器之间会保持打开状态,实现随时发送消息的功能,不需要频繁创建和关闭连接。
-
3. 心跳机制。为了保持连接的活跃性,
Websocket
使用心跳机制。客户端和服务器会定期发送一个特定的消息以确保连接处于活动状态,如果一方长时间没有收到心跳消息则认为连接断开并关闭连接。 -
4. 关闭连接。当客户端或服务器决定关闭连接是会发送一个
关闭帧
,接收到关闭帧
后另一方也会发送一个关闭帧,双方关闭连接。
实现
前端实现
created
阶段就初始化websocket连接。-
1. 创建WebSocket对象
var url = "ws://127.0.0.1:8899/ws?userid=12345"
this.websock = new WebSocket(url);
-
2. 建立连接
this.websock.onopen = this.websocketOnopen;
...
websocketOnopen: function () {
console.log("WebSocket连接成功");
}
-
3. 发送/接收数据在发送数据这里,
WebSocket
的send()
方法只能发送字符串、二进制数据。要发送json
字符串先将对象转换为json
字符串再发送。在这里会发送一个type
为request-data
,数据为12345的json
字符串到服务器中。
// 接收数据
websocketOnmessage: function (e) {
console.log("- 接收后端消息 -", e.data);
},
// 发送数据
websocketSend(text) {
const data = "12345"
try {
this.websock.send(JSON.stringify({type:'request-data',data}));
} catch (err) {
console.log("send failed (" + err.code + ")");
}
},
-
4. 错误处理
websocketOnerror: function (e) {
console.log("WebSocket连接发生错误");
this.reconnect();
},
-
5. 关闭连接/重新连接
// 关闭连接
websocketOnclose: function (e) {
console.log("connection closed (" + e.code + ")");
this.reconnect();
},
// 重新连接
reconnect() {
var that = this;
if (that.lockReconnect) return;
that.lockReconnect = true;
setTimeout(function () {
console.info("重新连接");
that.initWebSocket();
that.lockReconnect = false;
}, 5000);
},
后端实现
Gin
框架下实现websocket
连接首先需要安装github.com/gorilla/websocket
依赖,定义一个WebSocket升级器
,新增一个路由并将传入的HTTP
请求升级为websocket
请求。-
1. 安装依赖
go get github.com/gorilla/websocket
-
2. 定义websocket升级器
var UpGrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { //检查请求来源是否合法,返回true允许所有来源请求升级为websocket
return true
},
ReadBufferSize: 1024, // 读取缓冲区大小
WriteBufferSize: 1024, // 写入缓冲区大小
}
-
3. 新增路由并处理websocket请求
r.GET("/ws", WebSocketHandler)
.....
func WebSocketHandler(c *gin.Context) {
userID := c.Query("userid")
log.Println("userID->", userID)
// 获取WebSocket连接 下面这行代码使用的方法已经被弃用
//ws, err := websocket.Upgrade(c.Writer, c.Request, nil, 1024, 1024)
ws, err := UpGrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
panic(err)
}
// 处理WebSocket消息
for {
messageType, p, err := ws.ReadMessage()
if err != nil {
break
}
fmt.Println("msg:", string(p))
// 保存连接
mu.Lock()
connections[userID] = ws
mu.Unlock()
err = ws.WriteMessage(messageType, []byte("copy"))
if err != nil {
log.Println("websocket write Message ERROR")
}
}
// 关闭WebSocket连接
defer ws.Close()
}
-
4. 维护连接映射
var connections = make(map[string]*websocket.Conn)
var mu sync.Mutex
写在最后
https://github.com/FengZeHe/LearnGolang/tree/main/project/WebSocketDemo
原文始发于微信公众号(ProgrammerHe):Gin集成WebSocket
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/207867.html