golang,go,博客,开源,编程
在 Go 语言中实现 WebSocket 可以使用 gorilla/websocket
库,这是一个流行且成熟的 WebSocket 实现库,广泛应用于 Go Web 开发中。下面是一个简单的 Go WebSocket 实现示例,包含了 WebSocket 服务端和客户端的基本实现。
首先,需要安装 gorilla/websocket
包:
go get github.com/gorilla/websocket
WebSocket 服务器端会监听来自客户端的 WebSocket 连接请求,并能向客户端发送消息。
package main
import (
"fmt"
"log"
"net/http"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true // 忽略跨域检查
},
}
func handleConnection(w http.ResponseWriter, r *http.Request) {
// 升级 HTTP 请求为 WebSocket 协议
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Println(err)
return
}
defer conn.Close()
// 打印客户端连接信息
log.Printf("Client connected: %s", conn.RemoteAddr())
for {
// 读取客户端发送的消息
messageType, p, err := conn.ReadMessage()
if err != nil {
log.Println(err)
return
}
// 打印收到的消息
fmt.Printf("Received message: %s\n", p)
// 向客户端发送消息
err = conn.WriteMessage(messageType, p)
if err != nil {
log.Println(err)
return
}
}
}
func main() {
http.HandleFunc("/ws", handleConnection)
// 启动 WebSocket 服务,监听在 8080 端口
log.Println("WebSocket server starting on ws://localhost:8080")
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal("ListenAndServe:", err)
}
}
websocket.Upgrader
: 用于升级 HTTP 请求为 WebSocket 协议。CheckOrigin
函数用于跳过跨域检查,实际应用中可以根据需要做安全控制。handleConnection
: 处理每个 WebSocket 连接,持续接收客户端消息并将其返回给客户端。conn.ReadMessage
: 读取客户端发送的消息。conn.WriteMessage
: 向客户端发送消息。执行上述 Go 文件,启动 WebSocket 服务器:
go run main.go
服务会监听 ws://localhost:8080/ws
,接收 WebSocket 连接。
WebSocket 客户端可以使用 Go 的 gorilla/websocket
库通过 Dial
函数与服务器建立 WebSocket 连接。
package main
import (
"fmt"
"log"
"github.com/gorilla/websocket"
"os"
)
func main() {
// 连接到 WebSocket 服务器
url := "ws://localhost:8080/ws"
conn, _, err := websocket.DefaultDialer.Dial(url, nil)
if err != nil {
log.Fatal("dial:", err)
os.Exit(1)
}
defer conn.Close()
// 发送一条消息到服务器
message := "Hello, WebSocket server!"
err = conn.WriteMessage(websocket.TextMessage, []byte(message))
if err != nil {
log.Println("Error sending message:", err)
return
}
fmt.Println("Sent:", message)
// 读取服务器的响应
_, message, err := conn.ReadMessage()
if err != nil {
log.Println("Error reading message:", err)
return
}
fmt.Printf("Received: %s\n", message)
}
websocket.DefaultDialer.Dial
: 用于与 WebSocket 服务器建立连接。conn.WriteMessage
: 向 WebSocket 服务器发送消息。conn.ReadMessage
: 接收 WebSocket 服务器发送的消息。执行 WebSocket 客户端程序,客户端会连接到 WebSocket 服务器并发送消息。服务器会返回相同的消息。
go run client.go
你可以进一步扩展 WebSocket 服务器,支持如下功能:
例如,广播功能的扩展示例:
package main
import (
"fmt"
"log"
"net/http"
"github.com/gorilla/websocket"
"sync"
)
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
var clients = make(map[*websocket.Conn]bool) // 用来存储所有连接的客户端
var broadcast = make(chan string) // 用来广播消息
var mu sync.Mutex // 防止并发读写
func handleConnection(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Println(err)
return
}
defer conn.Close()
// 添加连接到客户端列表
mu.Lock()
clients[conn] = true
mu.Unlock()
for {
messageType, p, err := conn.ReadMessage()
if err != nil {
log.Println(err)
break
}
// 将收到的消息广播给所有连接的客户端
broadcast <- string(p)
// 向客户端回传消息
err = conn.WriteMessage(messageType, p)
if err != nil {
log.Println(err)
break
}
}
// 断开连接时删除客户端
mu.Lock()
delete(clients, conn)
mu.Unlock()
}
func broadcastMessages() {
for {
msg := <-broadcast
// 向所有连接的客户端发送消息
mu.Lock()
for client := range clients {
err := client.WriteMessage(websocket.TextMessage, []byte(msg))
if err != nil {
log.Println("Error broadcasting message:", err)
client.Close()
delete(clients, client)
}
}
mu.Unlock()
}
}
func main() {
http.HandleFunc("/ws", handleConnection)
go broadcastMessages()
log.Println("WebSocket server starting on ws://localhost:8080")
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal("ListenAndServe:", err)
}
}
在这个扩展中,服务器会将每个客户端的消息广播给所有其他客户端。
通过 gorilla/websocket
库,Go 可以轻松实现 WebSocket 服务端和客户端,支持全双工、实时消息交换。你可以基于此基础扩展更多功能,如身份验证、心跳检测和消息广播等。