Unix域套接字是进程间通信的一种常用方式,它不需要经过网络协议栈,仅在内核中完成数据传递,非常适合同一台机器上不同语言编写的程序之间的通信场景。PHP和Go都原生支持Unix域套接字的创建和使用,两者配合可以实现高效的本地数据交互。

Go端服务端实现
首先编写Go语言的服务端程序,负责监听Unix域套接字并接收PHP客户端的连接请求,处理完成后再返回响应数据。
package main
import (
"fmt"
"net"
"os"
"time"
)
func main() {
// 定义Unix域套接字文件路径
socketPath := "/tmp/php_go_comm.sock"
// 如果文件已存在则先删除,避免启动失败
if err := os.RemoveAll(socketPath); err != nil {
fmt.Println("删除旧套接字文件失败:", err)
return
}
// 监听Unix域套接字
listener, err := net.Listen("unix", socketPath)
if err != nil {
fmt.Println("监听套接字失败:", err)
return
}
defer listener.Close()
// 设置套接字文件权限,方便PHP进程访问
os.Chmod(socketPath, 0777)
fmt.Println("Go服务端已启动,监听路径:", socketPath)
for {
// 接受客户端连接
conn, err := listener.Accept()
if err != nil {
fmt.Println("接受连接失败:", err)
continue
}
// 开启协程处理每个连接
go handleConnection(conn)
}
}
// 处理单个连接的逻辑
func handleConnection(conn net.Conn) {
defer conn.Close()
// 设置连接超时时间
conn.SetDeadline(time.Now().Add(30 * time.Second))
buf := make([]byte, 1024)
for {
// 读取客户端发送的数据
n, err := conn.Read(buf)
if err != nil {
fmt.Println("读取数据失败:", err)
return
}
recvData := string(buf[:n])
fmt.Println("收到PHP客户端数据:", recvData)
// 构造响应数据
response := fmt.Sprintf("Go服务端已收到你的消息: %s, 当前时间: %s", recvData, time.Now().Format("2006-01-02 15:04:05"))
// 发送响应给客户端
_, err = conn.Write([]byte(response))
if err != nil {
fmt.Println("发送响应失败:", err)
return
}
}
}
PHP端客户端实现
接下来编写PHP客户端程序,负责连接Go服务端监听的Unix域套接字,发送数据并接收响应。
<?php
// 定义Unix域套接字文件路径,需要和Go服务端一致
$socketPath = "/tmp/php_go_comm.sock";
// 要发送的消息
$sendMsg = "Hello from PHP Client";
// 创建Unix域套接字
$socket = socket_create(AF_UNIX, SOCK_STREAM, 0);
if (!$socket) {
die("创建套接字失败: " . socket_strerror(socket_last_error()) . "n");
}
// 连接Go服务端
if (!socket_connect($socket, $socketPath)) {
die("连接服务端失败: " . socket_strerror(socket_last_error($socket)) . "n");
}
echo "PHP客户端已连接到Go服务端n";
// 发送数据
socket_write($socket, $sendMsg, strlen($sendMsg));
echo "已发送消息: " . $sendMsg . "n";
// 接收响应数据
$response = socket_read($socket, 1024);
if ($response) {
echo "收到Go服务端响应: " . $response . "n";
}
// 关闭套接字连接
socket_close($socket);
?>
连接管理实践要点
连接生命周期管理
Go服务端通过defer conn.Close()保证每个连接在处理完成后自动关闭,避免连接泄漏。PHP客户端则在数据交互完成后主动调用socket_close关闭连接,双方都需要做好连接关闭的处理逻辑。
异常处理机制
Go服务端在监听和接受连接时需要处理各类异常,比如套接字文件被占用、权限不足等问题,同时给每个连接设置超时时间,避免无效连接占用资源。PHP客户端需要处理套接字创建失败、连接超时、读写错误等异常,必要时可以添加重试逻辑。
性能优化建议
- Go服务端可以使用连接池复用部分资源,减少频繁创建销毁连接的开销
- PHP客户端如果需要频繁通信,可以保持长连接而不是每次通信都重新创建连接
- 数据交互时尽量约定好数据格式,比如使用JSON格式封装数据,避免解析错误
- 生产环境中可以给套接字文件设置合理的权限,避免非授权进程访问
测试验证
先启动Go服务端程序,运行后会看到监听成功的提示,然后运行PHP客户端程序,就可以看到PHP发送的消息被Go服务端接收并返回响应,PHP端也能正确输出Go服务端的返回内容,说明整个通信流程已经打通。
Unix_domain_socketPHPGo进程间通信连接管理修改时间:2026-06-25 19:42:30