Maison > Article > développement back-end > Conseils de programmation Golang WebSocket : gestion des connexions simultanées
Golang est un langage de programmation puissant et son utilisation dans la programmation WebSocket est de plus en plus appréciée par les développeurs. WebSocket est un protocole basé sur TCP qui permet une communication bidirectionnelle entre le client et le serveur. Dans cet article, nous expliquerons comment utiliser Golang pour écrire un serveur WebSocket efficace qui gère plusieurs connexions simultanées en même temps. Avant de présenter les techniques, apprenons d'abord ce qu'est WebSocket.
Introduction à WebSocket
WebSocket est un protocole de communication full-duplex qui permet d'établir une connexion persistante entre le client et le serveur, permettant une communication bidirectionnelle en temps réel. Contrairement à HTTP, les connexions WebSocket sont bidirectionnelles et le serveur peut envoyer activement des messages au client sans avoir à attendre que le client en fasse la demande.
Dans une connexion WebSocket, une fois que le client lance une demande de connexion, le serveur peut utiliser la connexion TCP établie pour envoyer des données au client. Le client et le serveur peuvent surveiller et traiter les messages de manière événementielle. Lorsqu'un événement est déclenché, le client et le serveur peuvent recevoir les données envoyées par l'autre partie.
Conseils de programmation Golang WebSocket
Etudions maintenant comment utiliser Golang pour écrire un serveur WebSocket efficace qui gère plusieurs connexions simultanées en même temps. Voici quelques conseils sur la programmation Golang WebSocket :
Lors de l'écriture d'un serveur WebSocket, nous devons prendre en compte les connexions simultanées. Nous devons nous assurer que le serveur peut gérer plusieurs clients établissant des connexions simultanément tout en conservant l'indépendance de chaque connexion. Pour atteindre cet objectif, nous pouvons utiliser des goroutines et des canaux en langage Go.
Voici un exemple simple qui montre comment gérer plusieurs connexions simultanées à l'aide de goroutines et de canaux :
package main import ( "fmt" "log" "net/http" ) var clients = make(map[*websocket.Conn]bool) // connected clients var broadcast = make(chan []byte) // broadcast channel // Configure the upgrader var upgrader = websocket.Upgrader{} func main() { // Create a simple file server fs := http.FileServer(http.Dir("public")) http.Handle("/", fs) // Configure websocket route http.HandleFunc("/ws", handleConnections) // Start listening for incoming chat messages go handleMessages() // Start the server on localhost:8000 log.Println("http server started on :8000") err := http.ListenAndServe(":8000", nil) if err != nil { log.Fatal("ListenAndServe: ", err) } } func handleConnections(w http.ResponseWriter, r *http.Request) { // Upgrade initial GET request to a websocket ws, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Fatal(err) } // Make sure we close the connection when the function returns defer ws.Close() // Register our new client clients[ws] = true for { // Read in a new message _, msg, err := ws.ReadMessage() if err != nil { log.Printf("error: %v", err) delete(clients, ws) break } // Send the newly received message to the broadcast channel broadcast <- msg } } func handleMessages() { for { // Grab the next message from the broadcast channel msg := <-broadcast // Send it out to every client that is currently connected for client := range clients { err := client.WriteMessage(websocket.TextMessage, msg) if err != nil { log.Printf("error: %v", err) client.Close() delete(clients, client) } } } }
Étant donné que la connexion WebSocket est une connexion persistante, elle peut être interrompue pour diverses raisons, telles qu'une panne de réseau. ou redémarrage du navigateur. Afin d'éviter que cela ne se produise, nous devons envoyer un paquet de battements de cœur au client de temps en temps pour garantir que la connexion reste active.
Voici un exemple simple qui montre comment utiliser goroutine et timer pour implémenter des paquets de battements de cœur :
package main import ( "github.com/gorilla/websocket" "time" ) // Configure the upgrader var upgrader = websocket.Upgrader{} func handleConnection(ws *websocket.Conn) { // Set the read deadline for the connection ws.SetReadDeadline(time.Now().Add(5 * time.Second)) for { // Read a message from the client _, _, err := ws.ReadMessage() if err != nil { if websocket.IsCloseError(err, websocket.CloseAbnormalClosure) || websocket.IsCloseError(err, websocket.CloseGoingAway) { // The client has closed the connection return } else if netErr, ok := err.(net.Error); ok && netErr.Timeout() { // A timeout has occurred, send a ping message to the client ping(ws) } else { // Some other error has occurred log.Println(err) return } } } } // Send a PING message to the client func ping(ws *websocket.Conn) { if err := ws.WriteMessage(websocket.PingMessage, []byte{}); err != nil { log.Println(err) ws.Close() } } // Start the server on localhost:8000 func main() { http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) { ws, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Println(err) return } // Handle the connection using a goroutine go handleConnection(ws) }) http.ListenAndServe(":8000", nil) }
Enfin, nous devons considérer la déconnexion des connexions WebSocket. Lors de la mise en œuvre d'un serveur WebSocket, nous devons prendre en compte le cycle de vie de la connexion afin qu'une désinfection appropriée se produise lorsque les données sont transférées entre le client et le serveur.
Voici un exemple simple qui montre comment utiliser les instructions goroutine et select pour réaliser la déconnexion des connexions WebSocket :
package main import ( "github.com/gorilla/websocket" ) var clients = make(map[*websocket.Conn]bool) var broadcast = make(chan Message) var unregister = make(chan *websocket.Conn) func main() { http.HandleFunc("/ws", handleConnections) go handleMessages() http.ListenAndServe(":8000", nil) } type Message struct { Type int `json:"type"` Body string `json:"body"` } func handleConnections(w http.ResponseWriter, r *http.Request) { upgrader := websocket.Upgrader{} ws, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Println(err) return } defer ws.Close() clients[ws] = true for { var msg Message err := ws.ReadJSON(&msg) if err != nil { if websocket.IsCloseError(err, websocket.CloseGoingAway) { unregister <- ws break } log.Printf("error: %v", err) continue } broadcast <- msg } } func handleMessages() { for { select { case msg := <-broadcast: for client := range clients { err := client.WriteJSON(msg) if err != nil { log.Printf("error: %v", err) unregister <- client break } } case client := <-unregister: delete(clients, client) } } }
Résumé
Dans cet article, nous avons présenté quelques conseils sur la programmation Golang WebSocket. Nous avons appris comment utiliser des goroutines et des canaux pour gérer les connexions simultanées, comment envoyer des paquets de battement de cœur pour garantir que la connexion reste valide et comment effectuer les opérations de nettoyage appropriées lorsque la connexion est déconnectée. Nous espérons que ces conseils vous seront utiles pour écrire des serveurs WebSocket efficaces.
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!