ホームページ  >  記事  >  バックエンド開発  >  Go 言語 Websocket 開発: 多数の同時接続を処理する方法

Go 言語 Websocket 開発: 多数の同時接続を処理する方法

WBOY
WBOYオリジナル
2023-12-14 13:47:311269ブラウズ

Go 言語 Websocket 開発: 多数の同時接続を処理する方法

Go 言語 Websocket 開発: 多数の同時接続を処理する方法

Websocket は、ブラウザとブラウザの間に永続的な接続を確立する全二重通信プロトコルです。これにより、サーバーがクライアントにメッセージをアクティブに送信できるようになり、クライアントもこの接続を通じてサーバーにメッセージを送信できます。 Websocket は、リアルタイム性と効率性の高さにより、リアルタイム通信、インスタント チャット、その他のシナリオで広く使用されています。

ただし、実際のアプリケーションでは、多くの場合、多数の同時接続を処理する必要があります。開発プロセスでは、安定した信頼性の高いサービスを提供するために、サーバーの処理能力を最適化する方法を検討する必要があります。以下では、Go 言語を使用して WebSocket プログラムを開発する方法を紹介し、それを具体的なコード例と組み合わせて、多数の同時接続を処理する方法を示します。

まず、Websocket 接続を処理するには、Go 言語の標準ライブラリの net/http および github.com/gorilla/websocket パッケージを使用する必要があります。次に、接続リクエストを処理する handler 関数を作成し、その中にメッセージ送受信ロジックを実装します。

package main

import (
    "log"
    "net/http"

    "github.com/gorilla/websocket"
)

// 声明一个全局的websocket的upgrader
var upgrader = websocket.Upgrader{}

func main() {
    http.HandleFunc("/ws", handleWS)
    err := http.ListenAndServe(":8000", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

func handleWS(w http.ResponseWriter, r *http.Request) {
    // 将HTTP连接升级为Websocket连接
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println("Upgrade error: ", err)
        return
    }
    defer conn.Close()

    for {
        // 读取客户端发送的消息
        _, msg, err := conn.ReadMessage()
        if err != nil {
            log.Println("Read error: ", err)
            break
        }

        // 处理收到的消息
        handleMessage(msg)

        // 向客户端发送消息
        err = conn.WriteMessage(websocket.TextMessage, []byte("Server received: "+string(msg)))
        if err != nil {
            log.Println("Write error: ", err)
            break
        }
    }
}

func handleMessage(message []byte) {
    log.Println("Received message: ", string(message))
    // TODO: 处理消息逻辑
}

上記のコードでは、まずグローバル upgrader オブジェクトを作成して、HTTP 接続を Websocket 接続にアップグレードします。 handleWS 関数では、upgrader.Upgrade メソッドを使用して HTTP 接続を Websocket 接続にアップグレードし、conn.ReadMessage# を通じてクライアントによって送信されたメッセージを読み取ります。 ##、次に、handleMessage を呼び出してメッセージ ロジックを処理し、conn.WriteMessage を通じてメッセージをクライアントに送信します。

上記のコードは Websocket 接続を処理できます。次に、多数の同時接続を処理する方法を検討する必要があります。 Go 言語には、同時通信を実装するための

goutinechannel が用意されており、各接続を処理するための handleWS 関数内に goutine を作成できます。このようにして、各接続は相互に影響を与えることなく、独立した goroutine で実行できます。

func main() {
    http.HandleFunc("/ws", handleWS)
    err := http.ListenAndServe(":8000", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

func handleWS(w http.ResponseWriter, r *http.Request) {
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println("Upgrade error: ", err)
        return
    }
    defer conn.Close()

    go func() {
        for {
            _, msg, err := conn.ReadMessage()
            if err != nil {
                log.Println("Read error: ", err)
                break
            }

            handleMessage(msg)

            err = conn.WriteMessage(websocket.TextMessage, []byte("Server received: "+string(msg)))
            if err != nil {
                log.Println("Write error: ", err)
                break
            }
        }
    }()
}

上記のコードを変更することで、

go func() を使用して匿名関数を goroutine として作成します。この関数では、各接続のメッセージの読み取りと送信が行われます。処理されたロジックです。このようにして、各接続を独立した goroutine で実行して、同時処理の効果を実現できます。

接続を同時に処理することに加えて、Go 言語の

channel を使用して同時接続の数を制限することもできます。バッファーを使用して channel を作成し、メイン スレッドで新しい接続が受け入れられたときに、対応する groutin に渡すことができます。接続数が特定のしきい値に達すると、新しい接続は接続はブロックされます。接続が閉じられると、新しい接続を受け入れることができるように、channel からその接続を削除できます。

func main() {
    http.HandleFunc("/ws", handleWS)
    err := http.ListenAndServe(":8000", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

func handleWS(w http.ResponseWriter, r *http.Request) {
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println("Upgrade error: ", err)
        return
    }
    defer conn.Close()

    // 将连接传递给一个channel处理
    connections <- conn

    go func(conn *websocket.Conn) {
        for {
            _, msg, err := conn.ReadMessage()
            if err != nil {
                log.Println("Read error: ", err)
                break
            }

            handleMessage(msg)

            err = conn.WriteMessage(websocket.TextMessage, []byte("Server received: "+string(msg)))
            if err != nil {
                log.Println("Write error: ", err)
                break
            }
        }
    }(conn)
}

var (
    maxConnections = 100
    connections    = make(chan *websocket.Conn, maxConnections)
)

func main() {
    http.HandleFunc("/ws", handleWS)
    go handleConnections()
    err := http.ListenAndServe(":8000", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

func handleConnections() {
    for conn := range connections {
        // 当连接数达到maxConnections时,新连接将会被阻塞
        log.Println("New connection accepted!")
        go handleWS(conn)
    }
}

上記のコードでは、最初にバッファ付きの

connections チャネルを作成し、そのサイズを maxConnections に設定します。 handleWS 関数では、接続を connections チャネルに渡し、接続のメッセージ送受信ロジックを処理する goroutine を作成します。 handleConnections 関数では、for conn := rangeconnections を使用して新しい接続を受信し、それらを処理するための対応する ゴルーチンを作成します。

上記の最適化により、Go 言語で大量の Websocket 接続を効率的に処理できます。接続の数が多すぎる場合は、

goutinechannel を使用して、接続処理タスクを複数の goutine に分散して処理し、パフォーマンスを向上させることができます。サーバーの同時処理機能。

要約すると、Go 言語の標準ライブラリとサードパーティ パッケージを使用して Websocket 接続を処理し、

goutinechannel## を使用して効率的な同時処理を実現できます。 # 、多数の同時接続を処理するニーズを満たすため。合理的なコード設計と適切な最適化戦略を通じて、Websocket サービスに安定した信頼性の高いサポートを提供できます。 (注: 上記のコードは単なる例であり、特定のアプリケーション シナリオではさらなる最適化と改善が必要になる場合があります)

以上がGo 言語 Websocket 開発: 多数の同時接続を処理する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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