对于Web开发,Gin是一种非常出色的go语言框架,因为它具有出色的速度和抽象性。GinWebSocket是Gin框架的WebSocket包,允许在Gin中创建WebSocket端点。WebSocket是一种网络协议,它允许在客户端和服务器之间进行双向通信,并且非常适合需要实时通信的应用程序。
一、快速入门
在gin中的WebSocket处理过程中,要引入github.com/gin-gonic/gin、github.com/gin-gonic/gin/binding、github.com/gorilla/websocket这三个包。通过对这些包的导入,我们可以轻松地在网站上实现WebSocket。
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/gorilla/websocket"
)
//此处使用默认Engine
var upGrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
func Websocket(c *gin.Context) {
conn, err := upGrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
fmt.Println(err)
return
}
}
上述代码主要用于处理来自客户端的请求,首先使用 gin.Context 来获得 http.ResponseWriter 和 *http.Request,这些内容将用于WebSocket握手。
接下来,我们使用 gorilla/websocket 中的Upgrader类型来创建WebSocket连接并从其中获取来自客户端的消息和断开连接请求。
二、创建Websocket客户端
在Gin中,我们可以通过在浏览器中使用Javascript中的WebSocket对象来创建WebSocket客户端。
function connect() {
var socket = new WebSocket('ws://127.0.0.1:8080/ws');
socket.onmessage = function (msg) {
console.log('Received message from server: ' + msg.data);
};
socket.onerror = function (error) {
console.error('WebSocket error: ' + error);
};
socket.onclose = function () {
console.log('WebSocket connection closed');
};
socket.onopen = function (event) {
// Send an initial message
socket.send('I am the client and I'm listening!');
};
}
connect();
在上面的示例代码中,我们可以看到如何使用Javascript来连接到WebSocket服务器。浏览器使用WebSocket对象并传递要连接的服务器的地址,然后通过调用onopen、onmessage、onerror和onclose函数进行初始设置。
三、WebSocket中间件
GinWebSocket允许您使用WebSocket中间件针对使用WebSocket的请求提供通用处理程序。在使用WebSocket中间件时,将在WebSocket处理程序中自动注入WebsocketContext。
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "Hello world!",
})
})
r.Use(WebsocketMiddleware())
r.GET("/websocket", WebsocketHandler)
r.Run(":8080")
}
func WebsocketMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
conn, err := upGrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
http.NotFound(c.Writer, c.Request)
return
}
wc := &WebsocketContext{conn}
c.Set("ws", wc)
err = c.Next()
if err != nil {
wc.Close()
}
}
}
在上面的示例代码中,我们使用WebsocketMiddleware在请求进入WebSocket处理程序之前对其进行处理。然后我们使用Set方法设置一个WebSocket上下文,以便在WebsocketHandler中访问该上下文。
四、广播
在许多场景中,您可能希望将消息广播给多个WebSocket客户端。使用 ginWebSocket,我们可以轻松地实现这一点。
var clients = make(map[*websocket.Conn]bool) // connected clients
var broadcast = make(chan Message) // broadcast channel
type Message struct {
Message string `json:"message"`
}
func main() {
r := gin.Default()
r.Use(WebsocketMiddleware())
r.GET("/ws", WebsocketHandler)
go handleMessages()
r.Run(":8080")
}
func handleMessages() {
for {
// Grab the next message from the broadcast channel
msg := <-broadcast
// Send it out to every client that is currently connected
for client := range clients {
err := client.WriteJSON(msg)
if err != nil {
log.Printf("error: %v", err)
client.Close()
delete(clients, client)
}
}
}
}
func WebsocketHandler(c *gin.Context) {
conn, _ := upGrader.Upgrade(c.Writer, c.Request, nil)
clients[conn] = true
for {
var msg Message
err := conn.ReadJSON(&msg)
if err != nil {
log.Printf("error: %v", err)
delete(clients, conn)
break
}
broadcast <- msg
}
}
在上面的示例代码中,我们使用一个全局 map 变量 clients 来存储客户端连接,并且通过一个广播通道 broadcast 进行消息广播。
在WebsocketHandler中,我们使用 ReadJSON 方法从连接中读取消息,并将该消息发送到广播通道中;在handleMessages中,我们使用 range 语句循环所有连接并将消息发回给它们所有人。
五、多线程中协同工作
对于更大的应用程序,我们可能希望使用多个goroutine来处理WebSocket链接。当多个goroutine同时处理WebSocket请求时,我们需要确保它们之间通信的正确性。在这些情况下,可以使用goroutine-safe通道来确保正常的协同工作。
var clients = make(map[*websocket.Conn]bool) // connected clients
var broadcast = make(chan Message) // broadcast channel
type Message struct {
Message string `json:"message"`
}
func main() {
r := gin.Default()
r.Use(WebsocketMiddleware())
r.GET("/ws", WebsocketHandler)
go handleMessages()
r.Run(":8080")
}
func handleMessages() {
for {
// Grab the next message from the broadcast channel
msg := <-broadcast
// Send it out to every client that is currently connected
for client := range clients {
err := client.WriteJSON(msg)
if err != nil {
log.Printf("error: %v", err)
client.Close()
delete(clients, client)
}
}
}
}
func WebsocketHandler(c *gin.Context) {
conn, _ := upGrader.Upgrade(c.Writer, c.Request, nil)
clients[conn] = true
go func() {
for {
var msg Message
err := conn.ReadJSON(&msg)
if err != nil {
log.Printf("error: %v", err)
broadcast <- Message{Message: "A client has disconnected."}
delete(clients, conn)
return
}
msg.Message = fmt.Sprintf("Message received from %v: %v", conn.RemoteAddr(), msg.Message)
broadcast <- msg
}
}()
}
在上面的示例代码中,我们使用一个goroutine来处理conn.ReadJSON(),并在goroutine-safe通道中发送读取的消息。这是为了确保多个线程同时处理WebSocket请求时可以进行正确的协调和通信。
总结
通过这篇文章,您应该已经能够了解如何在 Gin 中使用 ginWebSocket。您还可以使用 ginWebSocket 提供的一些其他功能,例如在应用程序中使用更高效的二进制消息,以便更快地发送和接收大量数据。同时,在代码设计过程中一定要注意线程安全问题,保证多个goroutine之间的正确协作。
原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/151021.html
微信扫一扫
支付宝扫一扫