Maison > développement back-end > Golang > le corps du texte

Résoudre les problèmes de sécurité de concurrence dans les applications Websocket en langage Go

王林
Libérer: 2023-12-14 13:47:39
original
624 Les gens l'ont consulté

Résoudre les problèmes de sécurité de concurrence dans les applications Websocket en langage Go

WebSocket est un protocole de communication réseau moderne qui peut réaliser une communication bidirectionnelle en temps réel élevée. Le langage Go prend intrinsèquement en charge la concurrence, il fonctionne donc très bien dans les applications Websocket. Cependant, la concurrence pose également certains problèmes. Dans les applications Websocket, cela se reflète principalement dans la sécurité de la concurrence. Dans cet article, nous expliquerons et démontrerons comment résoudre les problèmes de sécurité de concurrence dans les applications Go Websocket.

  1. Contexte du problème

Dans une application Websocket, un client peut envoyer des messages au serveur à tout moment, et le serveur peut également envoyer des messages au client à tout moment. Par conséquent, les problèmes de concurrence doivent être pris en compte lors du traitement des messages Websocket. En langage Go, nous pouvons utiliser goroutine pour traiter les messages Websocket simultanément.

Cependant, la concurrence entraînera certains problèmes de sécurité, tels que des conditions de concurrence critique, des blocages, etc. Les conditions de concurrence peuvent entraîner des incohérences de données et des blocages peuvent provoquer le gel des programmes. Ainsi, dans les applications Websocket, nous devons résoudre ces problèmes de sécurité de concurrence.

  1. Solution

2.1 Verrouillage Mutex

Le verrouillage Mutex est l'un des mécanismes de contrôle de concurrence les plus courants dans le langage Go. Il protège les ressources partagées et empêche plusieurs goroutines d'accéder aux ressources partagées en même temps, garantissant ainsi l'exactitude et la cohérence des données.

Dans les applications Websocket, nous pouvons assurer la sécurité simultanée des ressources partagées grâce à des verrous mutex. Par exemple, le code suivant montre comment utiliser un verrou mutex pour assurer la sécurité de plusieurs goroutines écrivant sur une carte partagée en même temps :

type safeMap struct {
    m map[string]int
    sync.Mutex
}

func (sm *safeMap) Inc(key string) {
    sm.Lock()
    sm.m[key]++
    sm.Unlock()
}
Copier après la connexion

Dans cet exemple, nous intégrons un mutex de type sync.Mutex dans la structure safeMap Locks sont utilisés pour protéger les ressources partagées. Dans cette structure, nous définissons une variable de type carte m, qui représente les ressources à partager par plusieurs goroutines. Ensuite, nous définissons une méthode Inc pour que safeMap effectue des opérations d'auto-incrémentation sur les données de la carte. Dans la méthode Inc, nous verrouillons d'abord, puis effectuons l'opération d'incrémentation et enfin déverrouillons.

2.2 Concurrence sans verrouillage

Une autre façon de résoudre les problèmes de sécurité de la concurrence consiste à utiliser la concurrence sans verrouillage. La concurrence sans verrouillage évite la perte de performances causée par les verrouillages mutex en utilisant des algorithmes non bloquants. Il peut améliorer la simultanéité et le débit du système et est souvent utilisé dans les systèmes hautes performances, à faible latence et à haut débit.

En langage Go, nous pouvons utiliser la fonction d'opération atomique du package sync/atomic pour obtenir une concurrence sans verrouillage. Par exemple, le code suivant montre comment utiliser des opérations atomiques pour implémenter des opérations simultanées sur des variables partagées :

type Counter struct {
    count int32
}

func (c *Counter) Inc() {
    atomic.AddInt32(&c.count, 1)
}

func (c *Counter) Dec() {
    atomic.AddInt32(&c.count, -1)
}

func (c *Counter) Get() int32 {
    return atomic.LoadInt32(&c.count)
}
Copier après la connexion

Dans cet exemple, nous utilisons les fonctions AddInt32 et LoadInt32 du package atomique pour implémenter un compteur. Nous définissons une structure Counter, qui contient une variable count de type int32. La structure Counter implémente également trois méthodes, à savoir Inc, Dec et Get. Dans les méthodes Inc et Dec, nous utilisons l'opération atomique AddInt32 pour incrémenter et décrémenter le nombre de variables partagées. Dans la méthode Get, nous utilisons l'opération atomique LoadInt32 pour obtenir la valeur du nombre de variables partagées.

  1. Exemple de code

Voici un exemple de code pour une application Websocket qui utilise des verrous mutex pour garantir la sécurité de la concurrence :

package main

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

    "github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
}

type Connection struct {
    ws *websocket.Conn
    mu sync.Mutex
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

func handler(w http.ResponseWriter, r *http.Request) {
    c, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        fmt.Println(err)
        return
    }

    conn := &Connection{ws: c}

    go conn.WriteLoop()
    conn.ReadLoop()
}

func (conn *Connection) ReadLoop() {
    defer conn.ws.Close()
    for {
        _, message, err := conn.ws.ReadMessage()
        if err != nil {
            fmt.Println(err)
            break
        }

        fmt.Printf("Received message: %s
", message)
    }
}

func (conn *Connection) WriteLoop() {
    defer conn.ws.Close()
    for {
        conn.mu.Lock()
        err := conn.ws.WriteMessage(websocket.TextMessage, []byte("Hello, world!"))
        conn.mu.Unlock()
        if err != nil {
            fmt.Println(err)
            break
        }
    }
}
Copier après la connexion

Dans cet exemple, nous avons implémenté une application Websocket simple qui contient une lecture Obtenez une boucle de lecture pour les messages client et un WriteLoop pour envoyer des messages au client. Dans cette application, nous encapsulons la connexion de chaque client dans une structure de connexion et intégrons un mutex de type sync.Mutex. Nous utilisons ce mutex dans WriteLoop pour assurer la sécurité de concurrence de la ressource partagée conn.ws. En utilisant un verrou mutex, nous pouvons éviter le problème de plusieurs goroutines écrivant des données sur la même connexion Websocket en même temps.

Voici un exemple de code pour une application Websocket qui utilise des opérations atomiques pour obtenir une concurrence sans verrouillage :

package main

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

    "github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
}

type Connection struct {
    ws    *websocket.Conn
    count int32
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

func handler(w http.ResponseWriter, r *http.Request) {
    c, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        fmt.Println(err)
        return
    }

    conn := &Connection{ws: c}

    go conn.WriteLoop()
    conn.ReadLoop()
}

func (conn *Connection) ReadLoop() {
    defer conn.ws.Close()
    for {
        _, message, err := conn.ws.ReadMessage()
        if err != nil {
            fmt.Println(err)
            break
        }

        fmt.Printf("Received message: %s
", message)
    }
}

func (conn *Connection) WriteLoop() {
    defer conn.ws.Close()
    for {
        n := atomic.AddInt32(&conn.count, 1)
        if n > 10 {
            break
        }

        err := conn.ws.WriteMessage(websocket.TextMessage, []byte("Hello, world!"))
        if err != nil {
            fmt.Println(err)
            break
        }
    }
}
Copier après la connexion

Dans cet exemple, nous utilisons les fonctions AddInt32 et LoadInt32 du package atomique pour implémenter un compteur. Nous définissons une structure Connection, qui contient une variable count de type int32. La structure Connection implémente également deux méthodes, ReadLoop et WriteLoop. Dans la méthode WriteLoop, nous utilisons l'opération atomique AddInt32 pour incrémenter le nombre de variables partagées. Ensuite, nous déterminons si la valeur du compteur dépasse 10 et sortons de la boucle si c'est le cas. Dans cet exemple, au lieu d'utiliser un mutex, nous utilisons des opérations atomiques pour obtenir une concurrence sans verrouillage.

  1. Conclusion

Cet article décrit comment résoudre les problèmes de sécurité de concurrence dans les applications Websocket en langage Go. Nous proposons deux solutions : les verrous mutex et la concurrence sans verrou. Qu'il s'agisse d'un verrouillage mutex ou d'une concurrence sans verrouillage, la sécurité de la concurrence peut être garantie. La méthode à choisir dépend des scénarios et des exigences spécifiques de l'application. Nous montrons comment utiliser ces technologies à travers des exemples de codes spécifiques, dans l’espoir d’aider les lecteurs à mieux comprendre et appliquer ces technologies.

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!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!