在 PHP 中打开异步套接字
Posted
技术标签:
【中文标题】在 PHP 中打开异步套接字【英文标题】:Open asynchronous sockets in PHP 【发布时间】:2013-08-08 23:26:27 【问题描述】:我正在用 php 编写一个支持小范围的端口扫描器(例如,端口 21-25)。要扫描的端口和 IP 通过 AJAX 发送到服务器,然后 PHP 尝试在每个端口上打开一个套接字。成功则端口打开,超时则关闭端口。
目前,尽管同时为端口 21-25 发送所有 AJAX 请求,但每个套接字仅在最后一个关闭后才打开。因此,检查端口 21,关闭套接字,然后检查端口 22,依此类推。我想要的是同时检查所有端口,所以我会同时打开几个套接字。
我试过了:
$fp = @fsockopen($ip,$port,$errno,$errstr,2);
socket_set_nonblock($fp);
但这不起作用,因为我在套接字已经打开并等待响应之后设置非阻塞。我想在 PHP 中做的事情可能吗?
【问题讨论】:
请告诉我们您看到的行为。你怎么知道它不起作用?请提供您在创建套接字后运行的代码。你提供的是正确的,所以如果有问题,它可能在之后的代码中。您提供的代码没有显示“等待响应”的任何内容。此外,在创建后设置非阻塞(或将其设置回阻塞)很好 - 很确定没有其他方法。 @xaxxon 这适用于打算保持打开状态的套接字,但我只是在编写端口扫描器,因此它会打开一个套接字,然后在建立连接后立即关闭它。我只是在验证使用该 IP 和端口创建套接字是可能的,本质上。问题是 socket_set_nonblock() 在 2 秒的超时窗口期间没有生效,所以如果目标上没有打开端口,它将等待整整两秒,然后再尝试下一个套接字。 换句话说,超时窗口正在阻止其他套接字的建立。 我明白了。由于 fsockopen 在套接字成功连接之前不会返回,因此在连接完成或失败之前不会调用使其成为非阻塞的调用。 @pleasestand 的答案看起来不错 【参考方案1】:使用不同的函数:socket_create()
和 socket_connect()
而不是 fsockopen()
。这有效:
$socks = array();
for ($port = 21; $port <= 25; $port++)
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_nonblock($sock);
@socket_connect($sock, 'localhost', $port);
$socks[$port] = $sock;
$startTime = microtime(true);
while ($socks && microtime(true) - $startTime < 3)
$null = null;
$write = $socks;
socket_select($null, $write, $null, 1);
foreach ($write as $port => $sock)
$desc = "$port/tcp";
$errno = socket_get_option($sock, SOL_SOCKET, SO_ERROR);
if ($errno == 0)
echo "$desc open\n";
elseif ($errno == SOCKET_ECONNREFUSED)
echo "$desc closed\n";
elseif ($errno == SOCKET_ETIMEDOUT)
echo "$desc filtered\n";
else
$errmsg = socket_strerror($errno);
echo "$desc error $errmsg\n";
unset($socks[$port]);
socket_close($sock);
foreach ($socks as $port => $sock)
$desc = "$port/tcp";
echo "$desc filtered\n";
socket_close($sock);
【讨论】:
以上是关于在 PHP 中打开异步套接字的主要内容,如果未能解决你的问题,请参考以下文章