兩個 Go 程序之間的 WebSocket 通信
實現(xiàn)兩個 Go 服務(wù)之間做 WebSocket 通信要怎么做?本文做了介紹。
使用 WebSockets 時,一個程序必須充當(dāng)服務(wù)器。
但是可以有許多其他程序作為客戶端。在本文中,我們將創(chuàng)建一個服務(wù)器和一個客戶端
WebSocket Server
服務(wù)器的代碼非常簡單。因為我們不想重新發(fā)明輪子,所以我們將使用gobwas模塊
下面是運(yùn)行在端口 8080 上的 WebSocket 服務(wù)器的代碼
- package main
- import (
- "fmt"
- "github.com/gobwas/ws"
- "github.com/gobwas/ws/wsutil"
- "math/rand"
- "net/http"
- "strconv"
- )
- func main() {
- fmt.Println("Server started, waiting for connection from client")
- http.ListenAndServe(":8080", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- fmt.Println("Client connected")
- conn, _, _, err := ws.UpgradeHTTP(r, w)
- if err != nil {
- fmt.Println("Error starting socket server: " + err.Error())
- }
- go func() {
- defer conn.Close()
- for {
- msg, op, err := wsutil.ReadClientData(conn)
- if err != nil {
- fmt.Println("Error receiving data: " + err.Error())
- fmt.Println("Client disconnected")
- return
- }
- fmt.Println("Client message received with random number: " + string(msg))
- randomNumber := strconv.Itoa(rand.Intn(100))
- err = wsutil.WriteServerMessage(conn, op, []byte(randomNumber))
- if err != nil {
- fmt.Println("Error sending data: " + err.Error())
- fmt.Println("Client disconnected")
- return
- }
- fmt.Println("Server message send with random number " + randomNumber)
- }
- }()
- }))
- }
服務(wù)器除了等待連接之外什么都不做,打印接收到的數(shù)據(jù)并最后發(fā)送一條消息(隨機(jī)整數(shù))
如果客戶端斷開連接(或有人停止程序),它將打印有關(guān)此斷開連接的信息
WebSocket Client
客戶端的代碼類似。同樣,我們將使用gobwas模塊
客戶端正在通過端口 8080 連接到 localhost
- package main
- import (
- "context"
- "fmt"
- "github.com/gobwas/ws"
- "github.com/gobwas/ws/wsutil"
- "math/rand"
- "os"
- "strconv"
- "time"
- )
- func main() {
- fmt.Println("Client started")
- for {
- conn, _, _, err := ws.DefaultDialer.Dial(context.Background(), "ws://127.0.0.1:8080/")
- if err != nil {
- fmt.Println("Cannot connect: " + err.Error())
- time.Sleep(time.Duration(5) * time.Second)
- continue
- }
- fmt.Println("Connected to server")
- for i := 0; i < 10; i++ {
- randomNumber := strconv.Itoa(rand.Intn(100))
- msg := []byte(randomNumber)
- err = wsutil.WriteClientMessage(conn, ws.OpText, msg)
- if err != nil {
- fmt.Println("Cannot send: " + err.Error())
- continue
- }
- fmt.Println("Client message send with random number " + randomNumber)
- msg, _, err := wsutil.ReadServerData(conn)
- if err != nil {
- fmt.Println("Cannot receive data: " + err.Error())
- continue
- }
- fmt.Println("Server message received with random number: " + string(msg))
- time.Sleep(time.Duration(5) * time.Second)
- }
- err = conn.Close()
- if err != nil {
- fmt.Println("Cannot close the connection: " + err.Error())
- os.Exit(1)
- }
- fmt.Println("Disconnected from server")
- }
- }
這個客戶端除了連接、發(fā)送消息(隨機(jī)整數(shù))并打印發(fā)回的任何內(nèi)容之外沒有什么特別的
測試
左側(cè),服務(wù)器結(jié)果 右側(cè),客戶端結(jié)果
客戶端每 5 秒向服務(wù)器發(fā)送一個隨機(jī)數(shù)。服務(wù)器用另一個隨機(jī)數(shù)回復(fù)
如果您停止服務(wù)器,您將在客戶端看到服務(wù)器已斷開連接。如果您再次啟動服務(wù)器,客戶端將再次連接。
您可以以另一種方式期待相同的行為。如果停止客戶端,服務(wù)器將打印一條消息,表明客戶端已斷開連接。如果您再次運(yùn)行客戶端......好吧,它再次連接
因為 Go 經(jīng)常用于服務(wù)和/或微服務(wù),所以在這些服務(wù)之間進(jìn)行通信是有意義的 。