3

I'm trying to use a Unix socket to have PHP send IPC messages to Go. Everything seems to work, except that PHP seems to keep reading the response from the socket, and won't let go. (The browser load-spinner keeps going, and there's no page render.) I'm using flag PHP_NORMAL_READ in the PHP:socket_read() function, and explicitly sending "\n" from Go.

Watching the Go process in the terminal, everything appears to work correctly on that end.

Edit: I think it was a browser caching issue. If I send different data back for PHP to echo, everything works as expected. I also switched to fmt.Fprintln() to make sure I wasn't getting the newline wrong.

Go:

package main

import (
    "net"
    "fmt"
    "log"
    "os"
)

const socket_addr = "/tmp/odc_ws.sock"

func echoServer(c net.Conn){
    buf := make([]byte, 512)
    size, err := c.Read(buf)
    if err != nil {
        log.Fatal("Read error: ", err)
    }
    data := buf[0:size]     
    fmt.Println("Server received: ", string(data))

    // NEW CODE
    t := time.Now()
    retMsg := fmt.Sprintf("OK+ at %s", t)
    size, err = fmt.Fprintln(c, retMsg)     

    //size, err = c.Write(ok)

    if err == nil{
        fmt.Println("Wrote this many bytes: ", size)
    } else {
        log.Fatal("Write error: ", err)
    }
}

func main(){
    l, err := net.Listen("unix", socket_addr)
    if err != nil{
        fmt.Println("On noes: %s", err)
        return
    }
    defer l.Close()
    for{
        fd, err := l.Accept()
        if err != nil{
            log.Fatal("Accept error", err)
        }
        go echoServer(fd)
    }

}

PHP:

ob_implicit_flush();
$socket_file = "/tmp/odc_ws.sock";

if (($socket = socket_create(AF_UNIX, SOCK_STREAM, 0)) === false) {
    echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "<br>";
}
if (socket_connect($socket, $socket_file) === false) {
    echo "socket_connect() failed: reason: " . socket_strerror(socket_last_error($sock)) . "<br>";
}

$msg = 'PHP sent Go a message at ' . date('H:i:s');
$write_res = socket_write($socket, $msg, $msg_len = strlen($msg));
if($write_res != $msg_len){
    echo '<div>Socket write error: ' . socket_strerror( socket_last_error($socket) ) . '</div>';
}

while($read = socket_read($socket, 512, PHP_NORMAL_READ)){
    echo "<div>Server says: $read</div>";
}
socket_close($socket);
6
  • I'm not familiar with go but is it possible that ok := []byte( "OK\n" ) does not produce the right byte for '\n' that PHP is expecting? Commented Aug 23, 2013 at 17:25
  • It seems possible it is encoding \n in another encoding format that PHP isn't expecting like unicode. Commented Aug 23, 2013 at 17:29
  • You could use wireshark to see exactly what is sent across if you can't find an easier answer Commented Aug 23, 2013 at 17:32
  • You could also try running PHP in the terminal to see its output. Commented Aug 23, 2013 at 17:36
  • 1
    I can pretty much guarantee that that Go is sending the \n character and not something else. Teh problem is definitely on the php side but it's been more than 5 years since I did PHP so I'm not sure what exactly it is. Commented Aug 23, 2013 at 19:10

1 Answer 1

1

It is not a PHP issue; you are not closing the server connection, so PHP continues to wait for more data. Add a defer c.Close():

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

    buf := make([]byte, 512)
    size, err := c.Read(buf)
    if err != nil {

PHP_NORMAL_READ is to force socket_read to read lines of text rather than binary streams.

From the PHP docs on socket_read (emphasis mine)

socket_read() returns the data as a string on success, or FALSE on error (including if the remote host has closed the connection)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.