Rumah >pembangunan bahagian belakang >Golang >Bagaimana untuk menyediakan pelayan Go WebSocket?

Bagaimana untuk menyediakan pelayan Go WebSocket?

WBOY
WBOYasal
2024-05-31 22:47:59839semak imbas

Cara membina pelayan Go WebSocket: Pasang perpustakaan gorila/soket web. Buat pelayan HTTP untuk mengendalikan permintaan jabat tangan WebSocket. Tingkatkan permintaan HTTP kepada sambungan WebSocket. Mengendalikan mesej WebSocket di bahagian pelayan, termasuk menghantar dan menerima data. Pelayan boleh dilanjutkan untuk membolehkan pelanggan melanggan saluran tertentu dan menerima mesej hanya daripada saluran tersebut.

Go WebSocket 服务器如何搭建?

Bina pelayan Go WebSocket

WebSocket ialah protokol komunikasi dupleks penuh yang membolehkan pelanggan dan pelayan memindahkan data dalam kedua-dua arah melalui satu sambungan TCP. Bahasa Go menyediakan sokongan yang kuat untuk membina pelayan WebSocket. Artikel ini akan memperkenalkan cara menggunakan Go untuk mencipta pelayan WebSocket, dengan contoh praktikal.

Bermula

Pertama, anda memerlukan persekitaran pembangunan Go, yang termasuk pengkompil Go dan editor kod. Anda juga perlu memasang pustaka gorila/websocket, yang menyediakan pelaksanaan WebSocket dalam Go. gorilla/websocket 库,它提供了 Go 语言的 WebSocket 实现。

go get -u github.com/gorilla/websocket

创建服务器

WebSocket 服务器本质上是一个传统的 HTTP 服务器,但它处理的是 WebSocket 握手请求。下面是如何在 Go 中创建 WebSocket 服务器:

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/gorilla/websocket"
)

func main() {
    // 升级 HTTP 请求到 WebSocket 连接
    upgrader := websocket.Upgrader{
        ReadBufferSize:  1024,
        WriteBufferSize: 1024,
    }

    http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
        conn, err := upgrader.Upgrade(w, r, nil)
        if err != nil {
            log.Fatal(err)
        }

        // websocket.Conn 是一个双向的连接
        for {
            // 从客户端接收消息
            messageType, p, err := conn.ReadMessage()
            if err != nil {
                log.Fatal(err)
            }

            // 将消息返回客户端
            if err := conn.WriteMessage(messageType, p); err != nil {
                log.Fatal(err)
            }
        }
    })

    http.ListenAndServe(":8080", nil)
}

实战案例

现在,我们来扩展这个服务器,允许客户端订阅特定的频道并仅接收来自这些频道的消息。

package main

import (
    "fmt"
    "log"
    "net/http"
    "sync"

    "github.com/gorilla/websocket"
)

type channel struct {
    sync.Mutex
    clients map[*websocket.Conn]bool
}

var channels = struct {
    sync.RWMutex
    m map[string]*channel
}{m: make(map[string]*channel)}

func NewChannel(name string) *channel {
    channels.Lock()
    defer channels.Unlock()

    if _, ok := channels.m[name]; !ok {
        channels.m[name] = &channel{clients: make(map[*websocket.Conn]bool)}
    }
    return channels.m[name]
}

func main() {
    upgrader := websocket.Upgrader{
        ReadBufferSize:  1024,
        WriteBufferSize: 1024,
    }

    http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
        conn, err := upgrader.Upgrade(w, r, nil)
        if err != nil {
            log.Fatal(err)
        }

        // 订阅和取消订阅频道
        go func() {
            for {
                // 从客户端接收消息
                messageType, p, err := conn.ReadMessage()
                if err != nil {
                    log.Fatal(err)
                }

                // 如果消息是一种订阅请求,则将连接添加到相应频道
                if messageType == websocket.TextMessage && string(p)[:4] == "join" {
                    channelName := string(p)[5:]
                    channel := NewChannel(channelName)

                    // 锁定频道的客户端列表
                    channel.Lock()
                    channel.clients[conn] = true
                    // 解锁频道的客户端列表
                    channel.Unlock()
                }

                // 如果消息是一种取消订阅请求,则将连接从相应频道中移除
                if messageType == websocket.TextMessage && string(p)[:7] == "leave" {
                    channelName := string(p)[8:]
                    channel := NewChannel(channelName)

                    channel.Lock()
                    delete(channel.clients, conn)
                    channel.Unlock()
                }
            }
        }()

        // 广播消息到客户端
        go func() {
            for {
                // 分别广播来自每个频道的消息
                channels.RLock()
                for _, channel := range channels.m {
                    channel.RLock()
                    for client := range channel.clients {
                        if err := client.WriteMessage(websocket.TextMessage, "hello"); err != nil {
                            // 如果写入失败,则从频道中移除连接
                            channel.Lock()
                            delete(channel.clients, client)
                            channel.Unlock()
                        }
                    }
                    channel.RUnlock()
                }
                channels.RUnlock()
            }
        }()
    })

    http.ListenAndServe(":8080", nil)
}

现在,你可以启动服务器并使用 WebSocket 客户端连接到 /wsrrreee

Buat Pelayan🎜🎜Pelayan WebSocket pada asasnya ialah pelayan HTTP tradisional, tetapi ia mengendalikan permintaan jabat tangan WebSocket. Begini cara untuk mencipta pelayan WebSocket dalam Go: 🎜rrreee🎜 Contoh praktikal 🎜🎜 Sekarang, mari kita panjangkan pelayan ini untuk membolehkan pelanggan melanggan saluran tertentu dan menerima mesej hanya daripada saluran tersebut. 🎜rrreee🎜Kini anda boleh memulakan pelayan dan menggunakan klien WebSocket untuk menyambung ke titik akhir /ws, melanggan saluran dan menerima mesej daripada saluran. 🎜

Atas ialah kandungan terperinci Bagaimana untuk menyediakan pelayan Go WebSocket?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn