Maison >développement back-end >Golang >Comment réaliser une communication bidirectionnelle avec les sockets Unix en Go ?

Comment réaliser une communication bidirectionnelle avec les sockets Unix en Go ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-12-02 01:25:111073parcourir

How to Achieve Bidirectional Communication with Unix Sockets in Go?

Sockets Unix bidirectionnels dans Go

Lors de l'implémentation de sockets Unix dans Go, il est essentiel d'établir un canal de communication bidirectionnel pour permettre au client et au serveur d'envoyer et de recevoir des données . Cet article explore un problème fondamental rencontré lors de l'utilisation de sockets Unix : les connexions unidirectionnelles conduisant à une transmission de données dans une seule direction.

Comprendre le problème

Dans l'exemple de code fourni, le serveur peut recevoir des données de le client mais ne parvient pas à répondre avec des données. Ce problème vient du fait que l'appel c.Read() dans le code client n'est jamais suivi d'un appel c.Write(). En conséquence, le client ne parvient pas à lire la réponse du serveur, créant l'illusion d'une connexion unidirectionnelle.

Résoudre le problème

Pour établir une communication bidirectionnelle, nous devons modifier à la fois le client et le serveur. code.

Modification du serveur

Le code du serveur modifié introduit une instruction defer pour gérer la fermeture gracieuse de la connexion en cas de problème. erreur. De plus, nous utilisons break pour quitter la goroutine du lecteur lorsque cela est nécessaire.

package main

import (
    "log"
    "net"
)

func echoServer(c net.Conn) {
    defer c.Close()

    for {
        buf := make([]byte, 512)
        nr, err := c.Read(buf)
        if err != nil {
            return
        }

        data := buf[0:nr]
        println("Server got:", string(data))
        _, err = c.Write(data)
        if err != nil {
            log.Fatal("Write: ", err)
        }
    }
}

func main() {
    l, err := net.Listen("unix", "/tmp/echo.sock")
    if err != nil {
        log.Fatal("listen error:", err)
    }

    for {
        fd, err := l.Accept()
        if err != nil {
            log.Fatal("accept error:", err)
        }

        go echoServer(fd)
    }
}

Modification du client

Le code client modifié ajoute une goroutine de lecteur pour lire en continu les données entrantes du serveur. L'instruction defer garantit que la connexion est fermée à la fin de la fonction principale.

package main

import (
    "io"
    "log"
    "net"
    "time"
)

func reader(r io.Reader) {
    defer r.(net.Conn).Close()  // Ensure connection is closed even on panic

    buf := make([]byte, 1024)
    for {
        n, err := r.Read(buf[:])
        if err != nil {
            return
        }
        println("Client got:", string(buf[0:n]))
    }
}

func main() {
    c, err := net.Dial("unix", "/tmp/echo.sock")
    if err != nil {
        log.Fatal(err)
    }

    go reader(c)

    for {
        _, err := c.Write([]byte("hi"))
        if err != nil {
            log.Fatal(err)
            break
        }
        time.Sleep(1e9)
    }
}

Avec ces modifications, la communication client-serveur devient bidirectionnelle, permettant aux deux parties d'envoyer et de recevoir des données de manière transparente.

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