PHP to Go 使用 Unix 域套接字

Posted

技术标签:

【中文标题】PHP to Go 使用 Unix 域套接字【英文标题】:PHP to Go using Unix domain sockets 【发布时间】:2013-08-23 17:16:46 【问题描述】:

我正在尝试使用 Unix 套接字让 php 向 Go 发送 IPC 消息。一切似乎都正常,除了 PHP 似乎一直在读取来自套接字的响应,并且不会放手。 (浏览器加载微调器继续运行,没有页面渲染。)我在 PHP:socket_read() 函数中使用标志 PHP_NORMAL_READ,并从 Go 显式发送“\n”。

在终端中观察 Go 进程,一切似乎都正常运行。

编辑:我认为这是浏览器缓存问题。如果我将不同的数据发送回 PHP 以进行回显,一切都会按预期工作。我还切换到 fmt.Fprintln() 以确保我没有弄错换行符。

去:

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

【问题讨论】:

我对 go 不熟悉,但是 ok := []byte( "OK\n" ) 是否可能不会为 PHP 所期望的 '\n' 生成正确的字节? 它似乎可能以另一种 PHP 不期望的编码格式编码 \n,如 unicode。 如果找不到更简单的答案,您可以使用 wireshark 查看发送的确切内容 您也可以尝试在终端中运行 PHP 以查看其输出。 我几乎可以保证 Go 发送的是 \n 字符而不是其他字符。问题肯定是在 php 方面,但自从我做 PHP 以来已经 5 年多了,所以我不确定它到底是什么。 【参考方案1】:

这不是 PHP 问题;您没有关闭服务器连接,因此 PHP 继续等待更多数据。添加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 是强制socket_read 读取文本行而不是二进制流。

来自关于 socket_read 的 PHP 文档(重点是我的)

socket_read() 成功时将数据作为字符串返回,错误时返回 FALSE(包括远程主机是否已关闭连接

【讨论】:

以上是关于PHP to Go 使用 Unix 域套接字的主要内容,如果未能解决你的问题,请参考以下文章

go语言unix域套接字发送udp报文

将 Python xmlrpclib 与 unix 域套接字一起使用?

nginx 将数据不完整地传输到 unix 域套接字

没有这样的文件或目录:AH02454:FCGI:尝试连接到 Unix 域套接字 /var/run/php/php5.6-fpm.sock (*) failed

高流量站点NGINX与PHP-fpm配置优化

高流量站点NGINX与PHP-fpm配置优化