Go言語を使用したマルチスレッドWebsocket通信の実装方法

WBOY
リリース: 2023-12-14 13:45:44
オリジナル
1129 人が閲覧しました

Go言語を使用したマルチスレッドWebsocket通信の実装方法

近年、リアルタイム通信が基本的なニーズになっています。 WebSocket はリアルタイム通信のリーダーであり、クライアントとサーバー間のリアルタイム通信をより迅速かつ効果的に実現できます。 Go 言語も近年人気の言語であり、リアルタイム通信で広く使用されています。 Go言語の利点とマルチスレッド処理の特性を活かして、Websocketの通信機能をより効率的かつ安定的に実現できます。

この記事では Go 言語に焦点を当て、いくつかの重要な関数の実装を含む、Go 言語を使用してマルチスレッド Websocket 通信を実装する方法を紹介し、詳細なコード例を示します。

Websocket の実装

Go 言語を使用して Websocket 通信を実装する前に、Websocket 通信の基本的な知識を理解する必要があります。 Websocket は、HTTP と同様、TCP に基づくネットワーク プロトコルです。ただし、違いは、これが要求および応答モードではなく、クライアントとサーバー間の継続的な接続であり、両者間のリアルタイム通信が可能であることです。

Go 言語で Websocket 通信を実装する最初のステップは、「net/http」パッケージと「github.com/gorilla/websocket」パッケージをインポートすることです。このうち「net/http」はHTTPサーバーの作成に使用され、「github.com/gorilla/websocket」はWebsocket用のサードパーティパッケージです。このパッケージが利用できない場合は、「go get」コマンドを使用してインストールできます。

import (
    "fmt"
    "net/http"
    "github.com/gorilla/websocket"
)
ログイン後にコピー

Websocket 接続の作成

Go 言語の「http.HandleFunc()」メソッドを使用して、以下に示すように Websocket 接続を確立します。

func main() {
    http.HandleFunc("/", handleConnections)

    http.ListenAndServe(":4000", nil)
}
ログイン後にコピー

上記のコードでは、次のコードを使用します。 " http.HandleFunc()" メソッドは、Websocket 接続の確立を担当する "handleConnections" という名前のハンドラー関数を作成します。ご覧のとおり、Websocket 接続を確立するためのリクエスト パスはルート ディレクトリである「/」です。

接続リクエストの処理

Websocket 接続を確立した後、プロトコルのアップグレード、読み取りおよび書き込みキャッシュ サイズ、ハートビート タイムアウトなど、接続リクエストのいくつかの基本パラメータを設定する必要があります。

var upgrader = websocket.Upgrader{
    ReadBufferSize: 1024,
    WriteBufferSize: 1024,
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
}
ログイン後にコピー

上記のコードは「websocket.Upgrader」を使用して構成されており、「ReadBufferSize」と「WriteBufferSize」は読み取りおよび書き込みバッファ領域のサイズを指定し、「CheckOrigin」は「true」に設定されています。すべてのソース アクセス要求を示します。特定のソースが必要な場合は、特定の要件に従って設定できます。

接続リクエストの処理

Websocket 接続リクエストが処理された後、プロトコルのアップグレードのために標準の Websocket プロトコル ハンドシェイクに従う必要があります。 Go 言語では、プロトコル アップグレードでは、Upgrader を使用してプロトコル ハンドシェイクを実行し、接続ハンドル (conn) を返します。接続ハンドルは、Websocket 接続のライフ サイクル中にメッセージを送受信するために使用できます。

func handleConnections(w http.ResponseWriter, r *http.Request) {
    // 通过Upgrader进行协议升级
    ws, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        fmt.Println(err)
    }

    // 若协议升级成功,则跳转到另一个处理函数处理消息
    go handleMessages(ws)
}
ログイン後にコピー

handleConnections 関数では、プロトコルは最初に Upgrader を通じてアップグレードされます。アップグレードが成功したら、「go handleMessages(ws)」を呼び出して goroutine を起動し、Websocket メッセージの処理を開始します。

Websocket メッセージの処理

次のステップは、Websocket メッセージ部分を処理することです。 Go 言語では、無限ループを使用して Websocket メッセージの到着を監視し、それに応じて各メッセージを処理できます。

func handleMessages(ws *websocket.Conn) {
    for {
        messageType, p, err := ws.ReadMessage()
        if err != nil {
            fmt.Println(err)
            return
        }

        // 根据消息类型进行处理
        switch messageType {
        case websocket.TextMessage:
            // 处理text类型消息
            fmt.Println(string(p))
        case websocket.BinaryMessage:
            // 处理binary类型消息
            fmt.Println(p)
        }
    }
}
ログイン後にコピー

handleMessages 関数では、まず「ws.ReadMessage()」メソッドを使用して Websocket メッセージを読み取り、メッセージ タイプに従って処理します。

Websocket メッセージの送信

最後の部分は、Websocket メッセージの送信部分です。 Go 言語では、Websocket 接続ハンドル「ws」を使用してクライアントにデータを送信できます。

func sendMessage(ws *websocket.Conn, messageType int, message []byte) error {
    if err := ws.WriteMessage(messageType, message); err != nil {
        return err
    }

    return nil
}
ログイン後にコピー

sendMessage 関数では、まず「ws.WriteMessage()」メソッドを通じてメッセージをクライアントに送信します。

Websocket のマルチスレッド処理

Websocket 通信の効率を向上させるために、Websocket メッセージの処理にマルチスレッドを使用する必要があります。 Go言語ではゴルーチンを使用して同時処理を実装できます。

ゴルーチンの開始

Go 言語では、ゴルーチンの開始は非常に簡単で、関数の前に「go」を追加するだけです。

go handleMessages(ws)
ログイン後にコピー

ブロードキャスト メッセージ

実際の開発では、Websocket は通常、ブロードキャスト メッセージを実装する必要があります。つまり、接続されているすべてのクライアントにメッセージを送信します。 Go 言語では、マップを使用して接続されているすべてのクライアントを保存し、各クライアントをトラバースしてメッセージを順番に送信できます。

var clients = make(map[*websocket.Conn]bool) // 所有连接的客户端
var broadcast = make(chan []byte) // 广播通道

func main() {
    http.HandleFunc("/", handleConnections)
    go handleMessages()

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

func handleConnections(w http.ResponseWriter, r *http.Request) {
    // 通过Upgrader进行协议升级
    ws, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        fmt.Println(err)
    }

    // 若协议升级成功,则将客户端存入map
    clients[ws] = true
}

func handleMessages() {
    for {
        // 从广播通道中获取消息
        message := <- broadcast
        // 对所有连接的客户端发送消息
        for client := range clients {
            if err := client.WriteMessage(websocket.TextMessage, message); err != nil {
                fmt.Println(err)
                delete(clients, client)
                return
            }
        }
    }
}
ログイン後にコピー

上記のコードでは、ブロードキャスト メッセージを処理するためにブロードキャスト チャネル (ブロードキャスト) が実装されています。同時に、接続されているすべてのクライアントを保存するためのマップ (クライアント) が作成されます。 handleConnections 関数では、新しいクライアントが接続すると、それがクライアントに保存されます。 handleMessages 関数では、ブロードキャスト チャネルがそこから新しいメッセージを取得し、接続されているすべてのクライアントに送信します。

同時実行の安全性を確保する

Websocket メッセージを複数のスレッドで処理する際には、データの同時実行性の安全性を確保する必要があります。 Go 言語では、同時実行性のセキュリティ制御にロックを使用できます。この記事のサンプル コードでは、「sync.RWMutex」を使用して読み取り/書き込みロックを実装し、同時実行の安全性を確保しています。

var mutex = &sync.RWMutex{}

func handleConnections(w http.ResponseWriter, r *http.Request) {
    // 通过Upgrader进行协议升级
    ws, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        fmt.Println(err)
    }

    // 若协议升级成功,则将客户端存入map,并进行锁定
    mutex.Lock()
    clients[ws] = true
    mutex.Unlock()
}

func handleMessages() {
    for {
        // 从广播通道中获取消息,并加锁
        message := <- broadcast
        mutex.Lock()
        for client := range clients {
            if err := client.WriteMessage(websocket.TextMessage, message); err != nil {
                fmt.Println(err)
                client.Close()
                delete(clients, client)
            }
        }
        mutex.Unlock()
    }
}
ログイン後にコピー

handleConnections 関数では、接続が成功すると、クライアントがマップに追加され、ロックされます。 handleMessages 関数では、データのセキュリティを確保するために、新しいメッセージを処理する前にロックします。

要約すると、Go 言語を使用してマルチスレッド Websocket 通信を実装すると、Websocket 通信の効率と安定性が向上し、ブロードキャスト メッセージを簡単に実装できます。実際には、特定のニーズに応じて、より複雑な機能を実装できます。

以上がGo言語を使用したマルチスレッドWebsocket通信の実装方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!