ホームページ  >  記事  >  バックエンド開発  >  Go WebSocket サーバーをセットアップするにはどうすればよいですか?

Go WebSocket サーバーをセットアップするにはどうすればよいですか?

WBOY
WBOYオリジナル
2024-05-31 22:47:59810ブラウズ

Go WebSocket サーバーの構築方法: Gorilla/WebSocket ライブラリをインストールします。 WebSocket ハンドシェイク要求を処理する HTTP サーバーを作成します。 HTTP リクエストを WebSocket 接続にアップグレードします。データの送受信など、サーバー側で WebSocket メッセージを処理します。サーバーを拡張して、クライアントが特定のチャネルにサブスクライブし、それらのチャネルからのみメッセージを受信できるようにすることができます。

Go WebSocket 服务器如何搭建?

Go WebSocket サーバーを構築する

WebSocket は、クライアントとサーバーが単一の TCP 接続を介して双方向にデータを送信できるようにする全二重通信プロトコルです。 Go 言語は、WebSocket サーバーの構築を強力にサポートします。この記事では、Go を使用して WebSocket サーバーを作成する方法を実践的な例とともに紹介します。

はじめに

まず、Go コンパイラーとコード エディターを含む Go 開発環境が必要です。 Go で WebSocket 実装を提供する gorilla/websocket ライブラリもインストールする必要があります。 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

サーバーの作成🎜🎜 WebSocket サーバーは本質的には従来の HTTP サーバーですが、WebSocket ハンドシェイク リクエストを処理します。 Go で WebSocket サーバーを作成する方法は次のとおりです: 🎜rrreee🎜 実践例 🎜🎜 次に、クライアントが特定のチャネルにサブスクライブし、それらのチャネルからのみメッセージを受信できるように、このサーバーを拡張しましょう。 🎜rrreee🎜 これで、サーバーを起動し、WebSocket クライアントを使用して /ws エンドポイントに接続し、チャネルにサブスクライブし、チャネルからメッセージを受信できるようになります。 🎜

以上がGo WebSocket サーバーをセットアップするにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。