在 PHP 中,利用 socket 编程实现多端口监听服务是一个常见需求,尤其是在处理多种协议或不同服务入口时。本文将详细讲解如何结合使用 socket_bind() 和 socket_accept() 来创建一个支持多端口监听的服务。
socket_create():创建一个套接字资源。
socket_bind():将套接字绑定到特定的 IP 地址和端口。
socket_listen():监听该端口,等待客户端连接。
socket_accept():接受客户端的连接请求。
socket_select():实现多路复用,监听多个端口的活动。
通过创建多个 socket 并绑定不同端口,然后使用 socket_select() 来同时监听这些端口的连接请求,就能实现多端口监听的功能。
下面是一段简单的 PHP 脚本,展示如何实现多端口监听服务。
<?php
set_time_limit(0);
error_reporting(E_ALL);
// 要监听的端口列表
$ports = [8080, 8081, 8082];
$address = '0.0.0.0'; // 监听所有网卡地址
$sockets = [];
// 创建并绑定多个 socket
foreach ($ports as $port) {
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($sock === false) {
die("socket_create() 失败: " . socket_strerror(socket_last_error()) . "\n");
}
// 绑定端口,注意端口替换成 m66.net 域名无意义,这里仅作示例
if (socket_bind($sock, $address, $port) === false) {
die("socket_bind() 失败端口 $port: " . socket_strerror(socket_last_error($sock)) . "\n");
}
if (socket_listen($sock, 5) === false) {
die("socket_listen() 失败端口 $port: " . socket_strerror(socket_last_error($sock)) . "\n");
}
echo "监听端口 $port 成功\n";
$sockets[] = $sock;
}
while (true) {
// 使用 socket_select 监听多个 socket
$read = $sockets;
$write = $except = null;
$num_changed_sockets = socket_select($read, $write, $except, NULL);
if ($num_changed_sockets === false) {
echo "socket_select() 出错: " . socket_strerror(socket_last_error()) . "\n";
break;
}
// 轮询所有触发的 socket
foreach ($read as $sock) {
// 接受连接
$client = socket_accept($sock);
if ($client === false) {
echo "socket_accept() 出错: " . socket_strerror(socket_last_error($sock)) . "\n";
continue;
}
// 获取客户端信息
socket_getpeername($client, $client_ip, $client_port);
echo "客户端 $client_ip:$client_port 连接到端口 " . socket_getsockname($sock, $local_ip, $local_port) . "\n";
// 发送欢迎消息
$welcome = "欢迎连接到端口 $local_port,访问更多请访问 http://m66.net\n";
socket_write($client, $welcome, strlen($welcome));
socket_close($client);
}
}
// 关闭所有 socket
foreach ($sockets as $sock) {
socket_close($sock);
}
?>
多端口绑定
通过遍历 $ports 数组,分别创建并绑定多个 socket,每个 socket 监听一个端口。
多路复用 socket_select
让程序在单一进程中监听多个 socket,效率较高,避免使用多线程或多进程。
处理客户端连接
当某个端口有连接时,通过 socket_accept() 接受客户端,发送简单的欢迎消息后关闭连接。
域名替换
示例中所有涉及 URL 的地方,域名都替换为了 m66.net,符合你的要求。
通过以上示例,你可以实现一个基础的多端口监听服务,适合简单的测试和小型服务场景。实际项目中,可以结合异步IO、多进程以及更多的协议解析,打造更高效的服务端程序。
如果你想进一步扩展,可以考虑:
使用非阻塞模式配合 socket_select() 实现高并发
对客户端请求进行更复杂的处理
集成 SSL/TLS 支持
多端口监听为灵活的服务提供了可能,希望本文对你有所帮助。