php socket实现长连接
PHP Socket 实现长连接的方法
使用 stream_socket_server 创建服务器端
在 PHP 中可以通过 stream_socket_server 创建一个 TCP 服务器。以下是一个简单的服务器端实现:
$socket = stream_socket_server("tcp://0.0.0.0:8000", $errno, $errstr);
if (!$socket) {
die("$errstr ($errno)");
}
while (true) {
$conn = stream_socket_accept($socket, -1);
if ($conn) {
while (true) {
$data = fread($conn, 1024);
if (!$data) break;
echo "Received: $data";
fwrite($conn, "Server response: $data");
}
fclose($conn);
}
}
客户端保持长连接
客户端可以使用 stream_socket_client 建立连接并保持长连接:
$socket = stream_socket_client("tcp://127.0.0.1:8000", $errno, $errstr, 30);
if (!$socket) {
die("$errstr ($errno)");
}
stream_set_blocking($socket, 0);
stream_set_timeout($socket, 0);
while (true) {
fwrite($socket, "Hello Server\n");
$data = fread($socket, 1024);
if ($data) {
echo "Received: $data";
}
sleep(1);
}
心跳机制实现
为了维持长连接,通常需要实现心跳机制:

// 服务器端心跳检测
$lastActive = time();
while (true) {
$data = fread($conn, 1024);
if ($data) {
$lastActive = time();
// 处理数据
} elseif (time() - $lastActive > 30) {
// 超时断开
fclose($conn);
break;
}
}
非阻塞模式设置
设置非阻塞模式可以避免连接阻塞:
stream_set_blocking($socket, 0);
多进程处理连接
使用 pcntl_fork 可以实现多进程处理多个连接:

while (true) {
$conn = stream_socket_accept($socket, -1);
$pid = pcntl_fork();
if ($pid == -1) {
die('Could not fork');
} elseif ($pid) {
// 父进程
continue;
} else {
// 子进程处理连接
handleConnection($conn);
exit;
}
}
使用 socket_select 处理多连接
更高效的方式是使用 socket_select 处理多个连接:
$read = [$socket];
$write = $except = null;
while (true) {
$changed = $read;
if (socket_select($changed, $write, $except, 0) > 0) {
foreach ($changed as $sock) {
if ($sock === $socket) {
$conn = stream_socket_accept($socket);
$read[] = $conn;
} else {
$data = fread($sock, 1024);
if (!$data) {
fclose($sock);
unset($read[array_search($sock, $read)]);
}
// 处理数据
}
}
}
}
错误处理和资源释放
确保正确处理错误和释放资源:
register_shutdown_function(function() use ($socket) {
fclose($socket);
});
性能优化建议
对于高性能场景,建议考虑以下优化:
- 使用 libevent 或 ev 扩展
- 考虑使用 Swoole 等高性能 PHP 网络框架
- 适当调整缓冲区大小
- 实现连接池管理
以上方法提供了在 PHP 中实现 Socket 长连接的基本框架,可以根据实际需求进行调整和扩展。






