PHP可以异步使用套接字吗?

时间:2009-09-16 11:48:18

标签: php sockets scripting asynchronous webserver

典型的PHP套接字功能是同步的,并在等待传入连接和数据时停止线程。 (例如socket_readsocket_listen

如何异步执行相同的操作?所以我可以响应数据接收事件中的数据,而不是轮询数据等。

4 个答案:

答案 0 :(得分:18)

是的,这就是socket_set_nonblock()的用途。考虑到错误代码11 EWOULDBLOCK和115,EINPROGRESS假设的特殊含义,您的套接字交互代码需要以不同方式编写。

以下是来自PHP同步套接字轮询循环的一些有些虚构的示例代码,如下所示:

$buf = '';
$done = false;
do {
    $chunk = socket_read($sock, 4096);
    if($chunk === false) {
        $error = socket_last_error($sock);
        if($error != 11 && $error != 115) {
            my_error_handler(socket_strerror($error), $error);
            $done = true;
        }
        break;
    } elseif($chunk == '') {
        $done = true;
        break;
    } else { 
        $buf .= $chunk;
    }
} while(true);

答案 1 :(得分:4)

  

如何异步执行相同的操作?   所以我可以回复数据中的数据   收到的事件,而不是轮询   数据等

您需要执行脚本并发出stream_select以检查是否有任何数据要接收。处理并发回数据。

答案 2 :(得分:4)

术语“异步”经常在网络编程中被滥用。对于I / O,异步通常仅用作非阻塞的另一个单词。这意味着该过程能够在网络api上的呼叫完成传输之前继续。

对于一般的流程执行,异步意味着可以一次计算多个指令(同时执行。)

换句话说,异步I / O并非真正异步,除非使用多个线程允许多个读/写/接受同时发生 - 如果有数据,所有套接字必须等待同步非阻塞调用要读/写或不会阻塞,如果没有中断,读/写大文件仍然需要几秒甚至几分钟。请注意,这将需要客户端和服务器之间的完美流程,否则TCP本身将中断传输。例如,发送速度超过客户端可以下载的服务器会导致写入时阻塞。

因此从严格的角度来看,PHP无法执行异步网络,只能进行非阻塞。简而言之,当网络调用能够有效地读/写等时,过程的进展将停止。但是,当调用无法有效地读/写或以其他方式阻塞时,该过程将继续。在一个真正的异步系统中,该过程将继续,并且读/写将在不同的线程中完成。请注意,如果在不同的线程中完成,阻塞I / O仍然可以异步完成。

此外,如果不安装支持它的扩展,PHP无法执行事件驱动的I / O.否则,您需要进行某种形式的轮询才能在PHP中执行非阻塞I / O.如果使用socket_select,Chaos中的代码将是一个功能性非阻塞读取示例。

话虽如此,select函数仍然允许在PHP中实现真正的非阻塞行为。在C中,轮询服务在事件驱动下会有性能损失,因此我确信它对PHP来说是相同的。但是这个损失是纳秒 - 微秒,具体取决于套接字的数量,其中从非阻塞呼叫节省的时间通常是毫秒,或者如果呼叫等待,则甚至是秒。

答案 3 :(得分:0)

AFAIK PHP是严格单线程的,这意味着您无法异步执行此操作,因为脚本执行始终是线性的。

我已经做了一段时间了,但据我记得,你只能打开套接字,让脚本在接收数据时继续执行。