Socket.io
用于 Fiber 的 WebSocket 封装,支持事件,灵感来自 Socket.io
注意:需要 Go 1.20 及以上版本
安装
go get -u github.com/gofiber/fiber/v2
go get -u github.com/gofiber/contrib/socketio
签名
// Initialize new socketio in the callback this will
// execute a callback that expects kws *Websocket Object
// and optional config websocket.Config
func New(callback func(kws *Websocket), config ...websocket.Config) func(*fiber.Ctx) error
// Add listener callback for an event into the listeners list
func On(event string, callback func(payload *EventPayload))
// Emit the message to a specific socket uuids list
// Ignores all errors
func EmitToList(uuids []string, message []byte)
// Emit to a specific socket connection
func EmitTo(uuid string, message []byte) error
// Broadcast to all the active connections
// except avoid broadcasting the message to itself
func Broadcast(message []byte)
// Fire custom event on all connections
func Fire(event string, data []byte)
示例
package main
import (
"encoding/json"
"fmt"
"log"
"github.com/gofiber/contrib/socketio"
"github.com/gofiber/contrib/websocket"
"github.com/gofiber/fiber/v2"
)
// MessageObject Basic chat message object
type MessageObject struct {
Data string `json:"data"`
From string `json:"from"`
Event string `json:"event"`
To string `json:"to"`
}
func main() {
// The key for the map is message.to
clients := make(map[string]string)
// Start a new Fiber application
app := fiber.New()
// Setup the middleware to retrieve the data sent in first GET request
app.Use(func(c *fiber.Ctx) error {
// IsWebSocketUpgrade returns true if the client
// requested upgrade to the WebSocket protocol.
if websocket.IsWebSocketUpgrade(c) {
c.Locals("allowed", true)
return c.Next()
}
return fiber.ErrUpgradeRequired
})
// Multiple event handling supported
socketio.On(socketio.EventConnect, func(ep *socketio.EventPayload) {
fmt.Printf("Connection event 1 - User: %s", ep.Kws.GetStringAttribute("user_id"))
})
// Custom event handling supported
socketio.On("CUSTOM_EVENT", func(ep *socketio.EventPayload) {
fmt.Printf("Custom event - User: %s", ep.Kws.GetStringAttribute("user_id"))
// --->
// DO YOUR BUSINESS HERE
// --->
})
// On message event
socketio.On(socketio.EventMessage, func(ep *socketio.EventPayload) {
fmt.Printf("Message event - User: %s - Message: %s", ep.Kws.GetStringAttribute("user_id"), string(ep.Data))
message := MessageObject{}
// Unmarshal the json message
// {
// "from": "<user-id>",
// "to": "<recipient-user-id>",
// "event": "CUSTOM_EVENT",
// "data": "hello"
//}
err := json.Unmarshal(ep.Data, &message)
if err != nil {
fmt.Println(err)
return
}
// Fire custom event based on some
// business logic
if message.Event != "" {
ep.Kws.Fire(message.Event, []byte(message.Data))
}
// Emit the message directly to specified user
err = ep.Kws.EmitTo(clients[message.To], ep.Data, socketio.TextMessage)
if err != nil {
fmt.Println(err)
}
})
// On disconnect event
socketio.On(socketio.EventDisconnect, func(ep *socketio.EventPayload) {
// Remove the user from the local clients
delete(clients, ep.Kws.GetStringAttribute("user_id"))
fmt.Printf("Disconnection event - User: %s", ep.Kws.GetStringAttribute("user_id"))
})
// On close event
// This event is called when the server disconnects the user actively with .Close() method
socketio.On(socketio.EventClose, func(ep *socketio.EventPayload) {
// Remove the user from the local clients
delete(clients, ep.Kws.GetStringAttribute("user_id"))
fmt.Printf("Close event - User: %s", ep.Kws.GetStringAttribute("user_id"))
})
// On error event
socketio.On(socketio.EventError, func(ep *socketio.EventPayload) {
fmt.Printf("Error event - User: %s", ep.Kws.GetStringAttribute("user_id"))
})
app.Get("/ws/:id", socketio.New(func(kws *socketio.Websocket) {
// Retrieve the user id from endpoint
userId := kws.Params("id")
// Add the connection to the list of the connected clients
// The UUID is generated randomly and is the key that allow
// socketio to manage Emit/EmitTo/Broadcast
clients[userId] = kws.UUID
// Every websocket connection has an optional session key => value storage
kws.SetAttribute("user_id", userId)
//Broadcast to all the connected users the newcomer
kws.Broadcast([]byte(fmt.Sprintf("New user connected: %s and UUID: %s", userId, kws.UUID)), true, socketio.TextMessage)
//Write welcome message
kws.Emit([]byte(fmt.Sprintf("Hello user: %s with UUID: %s", userId, kws.UUID)), socketio.TextMessage)
}))
log.Fatal(app.Listen(":3000"))
}
支持的事件
常量 | 事件 | 描述 |
---|---|---|
EventMessage | message | 当接收到文本/二进制消息时触发 |
EventPing | ping | 更多详细信息在此 |
EventPong | pong | 参考 ping 的描述 |
EventDisconnect | disconnect | 断开连接时触发。断开连接事件中提供的错误信息,定义在 RFC 6455 第 11.7 节。 |
EventConnect | connect | 首次连接时触发 |
EventClose | close | 当连接由服务器主动关闭时触发。这与客户端断开连接不同 |
EventError | error | 出现错误时触发,也常用于调试 websockets |
事件 Payload 对象
变量 | 类型 | 描述 |
---|---|---|
Kws | *Websocket | 连接对象 |
Name | string | 事件的名称 |
SocketUUID | string | 唯一的连接 UUID |
SocketAttributes | map[string]string | 可选的 websocket 属性 |
Error | error | (可选) 由断开连接或错误事件触发 |
Data | []byte | 在 Message 和 Error 事件中使用的载荷,包含自定义事件的载荷 |
Socket 实例函数
Name | 类型 | 描述 |
---|---|---|
SetAttribute | void | 为特定的 socket 连接设置一个特定的属性 |
GetUUID | string | 获取 socket 连接的 UUID |
SetUUID | error | 设置 socket 连接的 UUID |
GetAttribute | string | 从 socket 属性中获取一个特定的属性 |
EmitToList | void | 将消息发送到特定的 socket UUID 列表 |
EmitTo | error | 发送到特定的 socket 连接 |
Broadcast | void | 广播给所有活跃连接,但不包括广播消息给自己 |
Fire | void | 触发自定义事件 |
Emit | void | 发送/写入消息到给定的连接 |
Close | void | 从服务器主动关闭连接 |
注意:可以直接从实例访问 FastHTTP 连接
kws.Conn