Maison développement back-end Golang Comment utiliser le langage Go pour développer un système de transmission de données en temps réel basé sur Websocket

Comment utiliser le langage Go pour développer un système de transmission de données en temps réel basé sur Websocket

Dec 18, 2023 pm 06:39 PM
go语言 websocket 实时数据传输

Comment utiliser le langage Go pour développer un système de transmission de données en temps réel basé sur Websocket

Comment utiliser le langage Go pour développer un système de transmission de données en temps réel basé sur Websocket, des exemples de code spécifiques sont nécessaires

Websocket est un protocole full-duplex, qui peut réaliser une transmission de données en temps réel sans actualiser la page. Dans les applications Web modernes, le transfert de données en temps réel constitue un élément crucial. Cet article expliquera comment utiliser le langage Go pour développer un système de transmission de données en temps réel basé sur Websocket, notamment comment implémenter du code côté serveur et côté client, et fournira des exemples de code spécifiques.

  1. Créer un serveur WebSocket

Pour créer un système de transmission de données en temps réel basé sur Websocket, vous devez d'abord créer un serveur Websocket. Dans Go, vous pouvez utiliser la bibliothèque gorilla/websocket pour créer un serveur Websocket.

Ce qui suit est un exemple de code pour un simple serveur Websocket :

package main

import (
    "fmt"
    "net/http"

    "github.com/gorilla/websocket"
)

// 定义升级器
var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
}

func serveWs(w http.ResponseWriter, r *http.Request) {
    // 升级请求为Websocket
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        fmt.Println(err)
        return
    }

    // 读取Websocket消息
    for {
        messageType, p, err := conn.ReadMessage()
        if err != nil {
            fmt.Println(err)
            return
        }

        // 处理消息
        fmt.Println(string(p))

        // 回复消息
        err = conn.WriteMessage(messageType, p)
        if err != nil {
            fmt.Println(err)
            return
        }
    }
}

func main() {
    http.HandleFunc("/ws", serveWs)
    http.ListenAndServe(":8080", nil)
}
Copier après la connexion

Dans cet exemple, nous définissons d'abord un programme de mise à niveau (upgrader), qui est utilisé pour mettre à niveau les connexions HTTP vers les connexions Websocket. Ensuite, nous définissons une fonction serveWs qui reçoit un rédacteur de réponse HTTP (w) et une requête HTTP (r) et met à niveau la connexion HTTP vers une connexion Websocket.

Dans la fonction serveWs, nous mettons d'abord à niveau la connexion HTTP vers une connexion Websocket. Nous utilisons ensuite une boucle pour lire les messages Websocket. Une fois que nous avons lu le message, nous le traitons et renvoyons le même message au client.

Enfin, dans la fonction main, on associe la fonction serveWs au chemin /ws et on démarre le serveur HTTP sur le port 8080.

  1. Créer un client Websocket

Avant de créer le client Websocket, nous devons créer une page HTML qui communiquera avec le serveur via Websocket. Voici un exemple de code pour une page HTML de base :

<!DOCTYPE html>
<html>
<head>
    <title>Websocket Example</title>
</head>
<body>

    <textarea id="message"></textarea>
    <button onclick="send()">Send</button>

    <script>
    // 创建Websocket对象
    var ws = new WebSocket("ws://localhost:8080/ws");

    // 接收来自服务器的消息
    ws.onmessage = function(event) {
        console.log(event.data);
    };

    // 发送消息到服务器
    function send() {
        var input = document.getElementById("message");
        ws.send(input.value);
        input.value = "";
    }
    </script>

</body>
</html>
Copier après la connexion

Dans cet exemple, nous créons une zone de texte (message) et un bouton (envoyer). Lorsque l'utilisateur clique sur le bouton d'envoi, nous envoyons le texte saisi au serveur via Websocket.

En JavaScript, nous utilisons l'objet WebSocket pour créer un client Websocket. Dans notre exemple, le client Websocket se connectera au chemin /ws et lorsqu'il recevra des messages du serveur, il les affichera sur la console.

  1. Exécutez le serveur et le client Websocket

Pour exécuter le serveur et le client Websocket, suivez ces étapes :

  1. Dans un terminal, utilisez la ligne de commande pour accéder au répertoire contenant l'exemple de code de serveur.
  2. Entrez la commande suivante pour démarrer le serveur :
go run main.go
Copier après la connexion
  1. Dans votre navigateur, ouvrez l'URL suivante pour charger l'exemple de page HTML :
http://localhost:8080/
Copier après la connexion
  1. Entrez du texte dans la zone de texte et cliquez sur le bouton Envoyer. Vous devriez voir les messages envoyés et renvoyés par le serveur, ainsi que leur sortie dans la console du navigateur.
  2. Transmission de données en temps réel

Maintenant, nous avons réussi à créer un serveur et un client Websocket simples, mais ce n'est que le début. Pour réaliser une transmission de données en temps réel, nous devons modifier le code côté serveur et côté client et utiliser goroutine côté serveur pour gérer plusieurs connexions Websocket.

Ce qui suit est un exemple de code qui implémente la transmission de données en temps réel :

package main

import (
    "fmt"
    "net/http"
    "time"

    "github.com/gorilla/websocket"
)

// 定义升级器
var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
}

// 定义客户端
type Client struct {
    conn *websocket.Conn
    send chan []byte
}

// 处理客户端消息
func (c *Client) read() {
    defer func() {
        c.conn.Close()
    }()
    for {
        messageType, p, err := c.conn.ReadMessage()
        if err != nil {
            fmt.Println(err)
            return
        }
        // 处理消息
        fmt.Printf("Received: %s
", p)
    }
}

// 发送消息到客户端
func (c *Client) write() {
    defer func() {
        c.conn.Close()
    }()
    for {
        select {
        case message, ok := <-c.send:
            if !ok {
                c.conn.WriteMessage(websocket.CloseMessage, []byte{})
                return
            }
            writer, err := c.conn.NextWriter(websocket.TextMessage)
            if err != nil {
                return
            }
            writer.Write(message)
            if err := writer.Close(); err != nil {
                return
            }
        }
    }
}

// 定义Hub
type Hub struct {
    clients map[*Client]bool
    broadcast chan []byte
    register chan *Client
    unregister chan *Client
}

// 创建Hub
func newHub() *Hub {
    return &Hub{
        clients:    make(map[*Client]bool),
        broadcast:  make(chan []byte),
        register:   make(chan *Client),
        unregister: make(chan *Client),
    }
}

// 运行Hub
func (h *Hub) run() {
    for {
        select {
        case client := <-h.register:
            h.clients[client] = true
            fmt.Println("Client registered")
        case client := <-h.unregister:
            if _, ok := h.clients[client]; ok {
                delete(h.clients, client)
                close(client.send)
                fmt.Println("Client unregistered")
            }
        case message := <-h.broadcast:
            for client := range h.clients {
                select {
                case client.send <- message:
                    fmt.Printf("Sent: %s
", message)
                default:
                    close(client.send)
                    delete(h.clients, client)
                }
            }
        }
    }
}

func serveWs(hub *Hub, w http.ResponseWriter, r *http.Request) {
    // 升级请求为Websocket
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        fmt.Println(err)
        return
    }

    // 创建客户端
    client := &Client{
        conn: conn,
        send: make(chan []byte),
    }

    // 注册客户端
    hub.register <- client

    // 读取Websocket消息
    go client.read()

    // 发送Websocket消息
    go client.write()
}

func main() {
    // 创建Hub
    hub := newHub()

    // 运行Hub
    go hub.run()

    // 定期广播消息
    go func() {
        for {
            hub.broadcast <- []byte(fmt.Sprintf("Server Time: %s", time.Now().Format("2006-01-02 15:04:05")))
            time.Sleep(1 * time.Second)
        }
    }()

    // 启动HTTP服务器
    http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
        serveWs(hub, w, r)
    })
    http.Handle("/", http.FileServer(http.Dir(".")))
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        panic(err)
    }
}
Copier après la connexion

Dans cet exemple, nous définissons un Hub qui gère plusieurs clients Websocket. Chaque client dispose d'une goroutine de lecture (réception) et d'une goroutine d'écriture (envoi), qui gèrent respectivement les messages lus par le client et les messages envoyés au client.

En plus de traiter les messages des clients, Hub contient également un canal de diffusion pour diffuser des messages à tous les clients. Dans notre exemple, le Hub diffuse périodiquement la date et l'heure actuelles.

  1. Conclusion

Grâce aux exemples de code de cet article, nous avons appris à utiliser le langage Go pour créer un système de transmission de données en temps réel basé sur Websocket. Nous avons appris à utiliser la bibliothèque gorilla/websocket pour créer un serveur et un client Websocket, et implémenté comment gérer les entrées du client, comment envoyer des messages au client, et implémenté un Hub qui gère plusieurs clients Websocket, et implémenté la logique de diffuser des messages.

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

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Quelles bibliothèques sont utilisées pour les opérations du numéro de point flottantes en Go? Quelles bibliothèques sont utilisées pour les opérations du numéro de point flottantes en Go? Apr 02, 2025 pm 02:06 PM

La bibliothèque utilisée pour le fonctionnement du numéro de point flottante dans le langage go présente comment s'assurer que la précision est ...

Quel est le problème avec le fil de file d'attente dans GO's Crawler Colly? Quel est le problème avec le fil de file d'attente dans GO's Crawler Colly? Apr 02, 2025 pm 02:09 PM

Problème de threading de file d'attente dans Go Crawler Colly explore le problème de l'utilisation de la bibliothèque Crawler Crawler dans le langage Go, les développeurs rencontrent souvent des problèmes avec les threads et les files d'attente de demande. � ...

Dans Go, pourquoi les chaînes d'impression avec println et string () ont-elles des effets différents? Dans Go, pourquoi les chaînes d'impression avec println et string () ont-elles des effets différents? Apr 02, 2025 pm 02:03 PM

La différence entre l'impression de chaîne dans le langage go: la différence dans l'effet de l'utilisation de fonctions println et string () est en Go ...

Comment résoudre le problème de conversion de type user_id lors de l'utilisation du flux redis pour implémenter les files d'attente de messages dans le langage Go? Comment résoudre le problème de conversion de type user_id lors de l'utilisation du flux redis pour implémenter les files d'attente de messages dans le langage Go? Apr 02, 2025 pm 04:54 PM

Le problème de l'utilisation de Redessstream pour implémenter les files d'attente de messages dans le langage GO consiste à utiliser le langage GO et redis ...

Quelle est la différence entre la structure de définition des mots clés `var` et« type »dans le langage Go? Quelle est la différence entre la structure de définition des mots clés `var` et« type »dans le langage Go? Apr 02, 2025 pm 12:57 PM

Deux façons de définir les structures dans le langage GO: la différence entre les mots clés VAR et le type. Lorsque vous définissez des structures, GO Language voit souvent deux façons d'écrire différentes: d'abord ...

Que dois-je faire si les étiquettes de structure personnalisées à Goland ne sont pas affichées? Que dois-je faire si les étiquettes de structure personnalisées à Goland ne sont pas affichées? Apr 02, 2025 pm 05:09 PM

Que dois-je faire si les étiquettes de structure personnalisées à Goland ne sont pas affichées? Lorsque vous utilisez Goland pour le développement du langage GO, de nombreux développeurs rencontreront des balises de structure personnalisées ...

Quelles bibliothèques de GO sont développées par de grandes entreprises ou fournies par des projets open source bien connus? Quelles bibliothèques de GO sont développées par de grandes entreprises ou fournies par des projets open source bien connus? Apr 02, 2025 pm 04:12 PM

Quelles bibliothèques de GO sont développées par de grandes entreprises ou des projets open source bien connus? Lors de la programmation en Go, les développeurs rencontrent souvent des besoins communs, ...

Lorsque vous utilisez SQL.Open, pourquoi ne signale pas une erreur lorsque DSN passe vide? Lorsque vous utilisez SQL.Open, pourquoi ne signale pas une erreur lorsque DSN passe vide? Apr 02, 2025 pm 12:54 PM

Lorsque vous utilisez SQL.Open, pourquoi le DSN ne signale-t-il pas une erreur? En langue go, sql.open ...

See all articles