When implementing Unix sockets in Go, it's essential to establish a bidirectional communication channel to enable both the client and server to send and receive data. This article explores a fundamental issue encountered when using Unix sockets: unidirectional connections leading to data transmission in only one direction.
In the provided code example, the server can receive data from the client but fails to respond with data. This issue stems from the fact that the c.Read() call in the client code is never followed up by a c.Write() call. As a result, the client fails to read the server's response, creating the illusion of a unidirectional connection.
To establish bidirectional communication, we need to modify both the client and server code.
The modified server code introduces a defer statement to handle closing the connection gracefully in case of an error. Additionally, we utilize break to exit the reader goroutine when necessary.
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) } }
The modified client code adds a reader goroutine to continuously read incoming data from the server. The defer statement ensures the connection is closed upon termination of the main function.
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) } }
With these modifications, the client-server communication becomes bidirectional, allowing both parties to send and receive data seamlessly.
The above is the detailed content of How to Achieve Bidirectional Communication with Unix Sockets in Go?. For more information, please follow other related articles on the PHP Chinese website!