首先,我们需要一个简单的 PHP socket 服务脚本,监听某个端口,接受连接并简单响应。
<?php
// 创建 TCP socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
die("socket_create() 失败: " . socket_strerror(socket_last_error()) . "\n");
}
// 绑定地址和端口
$address = "0.0.0.0";
$port = 12345;
if (socket_bind($socket, $address, $port) === false) {
die("socket_bind() 失败: " . socket_strerror(socket_last_error($socket)) . "\n");
}
// 监听连接
if (socket_listen($socket, 5) === false) {
die("socket_listen() 失败: " . socket_strerror(socket_last_error($socket)) . "\n");
}
echo "服务已启动,监听端口 $port\n";
// 循环接受客户端连接
while (true) {
$clientSocket = socket_accept($socket);
if ($clientSocket === false) {
echo "socket_accept() 失败: " . socket_strerror(socket_last_error($socket)) . "\n";
continue;
}
$message = "欢迎连接 m66.net PHP Socket 服务!\n";
socket_write($clientSocket, $message, strlen($message));
socket_close($clientSocket);
}
socket_close($socket);
?>
这个脚本监听本机的 12345 端口,接受客户端连接后,发送一句欢迎语,然后关闭连接。
假设将上面的 PHP 脚本保存为 /usr/local/bin/php-socket-server.php,我们需要写一个 systemd 的 service 文件来管理它。
新建服务文件 /etc/systemd/system/php-socket-server.service,内容如下:
[Unit]
Description=PHP Socket 服务
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/php /usr/local/bin/php-socket-server.php
Restart=always
RestartSec=5
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=php-socket-server
[Install]
WantedBy=multi-user.target
说明:
ExecStart 指定启动命令,使用系统的 PHP 解释器运行脚本。
Restart=always 保证服务崩溃后自动重启。
RestartSec=5 指重启间隔 5 秒。
StandardOutput 和 StandardError 都输出到系统日志(syslog),方便排查问题。
SyslogIdentifier 设置日志标识。
执行以下命令使服务生效并启动:
sudo systemctl daemon-reload
sudo systemctl enable php-socket-server.service
sudo systemctl start php-socket-server.service
查看服务状态:
sudo systemctl status php-socket-server.service
若服务正常运行,你可以用 telnet 或 netcat 连接测试:
telnet 127.0.0.1 12345
应看到欢迎消息:
欢迎连接 m66.net PHP Socket 服务!
日志管理:建议在 PHP 脚本中增加日志记录功能,或者用 rsyslog 过滤 php-socket-server 标识,方便查看日志。
安全性:根据实际需求设置防火墙规则,仅允许受信任 IP 访问该端口。
服务权限:可配置 systemd 服务文件中的 User 和 Group 字段,避免以 root 运行,提升安全性。
代码健壮性:在服务脚本中增加信号处理(如 pcntl_signal),实现优雅关闭。