Maison  >  Article  >  développement back-end  >  Comment implémenter une communication Websocket multithread à l'aide du langage Go

Comment implémenter une communication Websocket multithread à l'aide du langage Go

WBOY
WBOYoriginal
2023-12-14 13:45:441157parcourir

Comment implémenter une communication Websocket multithread à laide du langage Go

Ces dernières années, la communication en temps réel est devenue un besoin fondamental. WebSocket est un leader en matière de communication en temps réel. Il peut réaliser une communication en temps réel entre le client et le serveur plus rapidement et plus efficacement. Le langage Go est également devenu un langage populaire ces dernières années et est largement utilisé dans les communications en temps réel. Profitant des avantages du langage Go et des caractéristiques du traitement multithread, la fonction de communication de Websocket peut être réalisée de manière plus efficace et plus stable.

Cet article se concentrera sur le langage Go et présentera comment l'utiliser pour implémenter une communication Websocket multithread, y compris certaines implémentations de fonctions importantes, et fournira des exemples de code détaillés.

Implémentation de Websocket

Avant d'utiliser le langage Go pour implémenter la communication Websocket, vous devez comprendre certaines connaissances de base de la communication Websocket. Websocket, comme HTTP, est un protocole réseau basé sur TCP. Mais la différence est qu'il ne s'agit pas d'un mode requête et réponse, mais d'une connexion continue entre le client et le serveur, permettant une communication en temps réel entre les deux parties.

En langage Go, la première étape pour implémenter la communication Websocket est d'importer les packages "net/http" et "github.com/gorilla/websocket". Parmi eux, « net/http » est utilisé pour créer un serveur HTTP et « github.com/gorilla/websocket » est un package tiers pour Websocket. Si ce package n'est pas disponible, vous pouvez utiliser la commande "go get" pour l'installer.

import (
    "fmt"
    "net/http"
    "github.com/gorilla/websocket"
)

Créez une connexion Websocket

Utilisez la méthode "http.HandleFunc()" pour établir une connexion Websocket en langage Go, comme indiqué ci-dessous :

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

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

Le code ci-dessus utilise la méthode "http.HandleFunc()" pour créer une connexion nommée fonction de traitement " handleConnections ", qui est chargée d'établir une connexion Websocket. Comme vous pouvez le voir, le chemin de requête pour établir une connexion Websocket est "/", qui est le répertoire racine.

Traitement des demandes de connexion

Après avoir établi une connexion Websocket, vous devez configurer certains paramètres de base pour la demande de connexion, tels que la mise à niveau du protocole, la taille du cache de lecture et d'écriture, le délai d'expiration du battement de cœur, etc.

var upgrader = websocket.Upgrader{
    ReadBufferSize: 1024,
    WriteBufferSize: 1024,
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
}

Le code ci-dessus est configuré à l'aide de "websocket.Upgrader", où "ReadBufferSize" et "WriteBufferSize" spécifient la taille du tampon de lecture et d'écriture, et "CheckOrigin" est défini sur "true", indiquant que toutes les demandes d'accès à la source sont acceptés. Si une source spécifique est requise, elle peut être définie en fonction d'exigences spécifiques.

Traitement des demandes de connexion

Une fois la demande de connexion Websocket traitée, la prise de contact standard du protocole Websocket doit être suivie pour la mise à niveau du protocole. En langage Go, la mise à niveau du protocole peut utiliser Upgrader pour effectuer une négociation de protocole et renvoyer le handle de connexion (conn). Le handle de connexion peut être utilisé pour envoyer et recevoir des messages pendant le cycle de vie de la connexion 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)
}

Dans la fonction handleConnections, le protocole est d'abord mis à niveau via Upgrader. Si la mise à niveau réussit, appelez « go handleMessages(ws) » pour démarrer goroutine et commencer à traiter les messages Websocket.

Traitement des messages Websocket

L'étape suivante consiste à traiter les messages Websocket. Dans le langage Go, vous pouvez utiliser une boucle infinie pour surveiller l'arrivée des messages Websocket, puis traiter chaque message en conséquence.

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)
        }
    }
}

Dans la fonction handleMessages, utilisez d'abord la méthode "ws.ReadMessage()" pour lire le message Websocket et le traiter en fonction du type de message.

Envoyer un message Websocket

La dernière partie est la partie d'envoi du message Websocket. Dans le langage Go, vous pouvez utiliser le handle de connexion Websocket « ws » pour envoyer des données au client.

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

    return nil
}

Dans la fonction sendMessage, envoyez d'abord le message au client via la méthode "ws.WriteMessage()".

Traitement Websocket multithread

Afin d'améliorer l'efficacité de la communication Websocket, le multithread doit être utilisé pour traiter les messages Websocket. Dans le langage Go, vous pouvez utiliser goroutine pour implémenter un traitement simultané.

Démarrer goroutine

En langage Go, démarrer une goroutine est très simple, il suffit d'ajouter "go" avant la fonction.

go handleMessages(ws)

Message de diffusion

Dans le développement réel, Websocket doit généralement implémenter des messages de diffusion, c'est-à-dire envoyer un message à tous les clients connectés. Dans le langage Go, vous pouvez utiliser une carte pour stocker tous les clients connectés, puis parcourir et envoyer des messages à chaque client tour à tour.

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
            }
        }
    }
}

Dans le code ci-dessus, un canal de diffusion (broadcast) est implémenté pour traiter les messages diffusés. En même temps, une carte (clients) est créée pour stocker tous les clients connectés. Dans la fonction handleConnections, lorsqu'un nouveau client se connecte, il sera stocké dans clients. Dans la fonction handleMessages, le canal de diffusion en reçoit de nouveaux messages et les envoie à tous les clients connectés.

Assurer la sécurité de la concurrence

Lorsque le multithreading traite les messages Websocket, il est nécessaire de garantir la sécurité de la concurrence des données. Dans le langage Go, vous pouvez utiliser des verrous pour le contrôle de sécurité simultanée. Dans l'exemple de code de cet article, « sync.RWMutex » est utilisé pour implémenter des verrous en lecture-écriture afin de garantir la sécurité de la concurrence.

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()
    }
}

Dans la fonction handleConnections, une fois la connexion réussie, le client est ajouté à la carte et verrouillé. Dans la fonction handleMessages, verrouillez avant de traiter de nouveaux messages pour garantir la sécurité des données.

En résumé, l'utilisation du langage Go pour implémenter une communication Websocket multithread peut améliorer l'efficacité et la stabilité de la communication Websocket et peut facilement implémenter des messages de diffusion. En pratique, des fonctions plus complexes peuvent être mises en œuvre en fonction de besoins spécifiques.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn