在 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 中打开异步套接字的主要内容,如果未能解决你的问题,请参考以下文章

在 Iphone SDK 上接收带有异步 Udp 套接字的 UPS 包时出现问题

.Net 异步套接字操作限制?

在 Delphi 中进行异步套接字编程的惯用方法是啥?

如何在 C# 应用程序中取消异步发送套接字

在 Swift 中为聊天应用程序保持套接字打开

在异步套接字中向特定客户端发送数据