在使用 PHP 进行网络编程时,socket_accept() 是接受客户端连接的核心函数。面对 DoS(Denial of Service)攻击,攻击者通常会通过大量恶意连接请求,耗尽服务器资源,导致服务器无法正常响应合法用户请求。本文将讲解如何通过限制 socket_accept() 接受的最大连接数,有效防止服务器被恶意拖垮。
DoS 攻击中,攻击者制造大量连接请求占满服务器的并发连接数,导致服务器无法处理新的正常请求。限制最大连接数,确保服务器在资源许可范围内只处理一定数量的客户端连接,可以有效降低这种攻击带来的影响。
使用变量计数当前已建立的连接数。
在接收到新的连接时,判断当前连接数是否超过限制。
超过限制时拒绝连接(关闭新连接),不再调用 socket_accept() 处理。
连接关闭时,及时减少连接计数。
下面的代码示范了如何在 PHP 中实现基于 socket_accept() 的最大连接数限制,假设最大连接数为 100:
<?php
set_time_limit(0);
error_reporting(E_ALL);
$address = '0.0.0.0';
$port = 12345;
$maxConnections = 100;
$currentConnections = 0;
// 创建 TCP Socket
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($sock, $address, $port) or die('绑定失败');
socket_listen($sock);
echo "服务器启动,监听 {$address}:{$port}\n";
$clients = [];
while (true) {
// 判断是否超过最大连接数
if ($currentConnections < $maxConnections) {
// 非阻塞模式接受新连接
socket_set_nonblock($sock);
$client = @socket_accept($sock);
if ($client !== false) {
// 新连接成功,计数加一
$currentConnections++;
$clients[] = $client;
// 设置客户端socket为非阻塞
socket_set_nonblock($client);
echo "新客户端连接,当前连接数: $currentConnections\n";
}
} else {
// 超出最大连接数,拒绝新连接(可选等待短暂时间)
usleep(100000); // 100ms
}
// 轮询处理已连接客户端的数据
foreach ($clients as $key => $clientSocket) {
$data = @socket_read($clientSocket, 2048, PHP_NORMAL_READ);
if ($data === false) {
// 连接断开,移除客户端
socket_close($clientSocket);
unset($clients[$key]);
$currentConnections--;
echo "客户端断开,当前连接数: $currentConnections\n";
continue;
} elseif ($data !== '') {
$data = trim($data);
if ($data === 'quit') {
// 客户端主动断开连接
socket_close($clientSocket);
unset($clients[$key]);
$currentConnections--;
echo "客户端主动断开,当前连接数: $currentConnections\n";
continue;
}
// 处理客户端发送的数据
$response = "服务器收到: {$data}\n";
socket_write($clientSocket, $response, strlen($response));
}
}
usleep(50000); // 减少CPU占用
}
?>
使用 $currentConnections 记录当前活跃连接数。
只在未超出最大连接数时调用 socket_accept() 接收新连接。
新连接创建后将客户端 socket 保存到 $clients 数组,并设置为非阻塞模式。
通过轮询 $clients,读取客户端数据,响应后继续监听。
如果客户端断开或者发送 quit 指令,关闭 socket 并减少连接计数。
使用 usleep() 减少 CPU 过度占用。
设置超时:检测客户端连接空闲时间,超时自动断开。
限制单IP连接数:防止单一IP制造大量连接。
使用防火墙:在服务器层面限制异常连接。
使用负载均衡:分散请求压力。
监控日志:及时发现异常流量。
通过在 PHP 的 socket 服务器中限制最大连接数,可以有效抵御一定程度的 DoS 攻击,避免服务器资源被恶意耗尽。结合其他安全措施,能为服务器提供更坚实的防护,保障服务的稳定运行。