PHP 可以异步使用套接字吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1432477/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can PHP asynchronously use sockets?
提问by TheFlash
Typical PHP socket functionality is synchronous, and halts the thread when waiting for incoming connections and data. (eg. socket_readand socket_listen)
典型的 PHP 套接字功能是同步的,并在等待传入连接和数据时暂停线程。(例如socket_read和socket_listen)
How do I do the same asynchronously? so I can respond to data in a data received event, instead of polling for data, etc.
我如何异步执行相同的操作?所以我可以在数据接收事件中响应数据,而不是轮询数据等。
采纳答案by chaos
Yup, that's what socket_set_nonblock()is for. Your socket interaction code will need to be written differently, taking into account the special meanings that error codes 11, EWOULDBLOCK, and 115, EINPROGRESS, assume.
是的,这socket_set_nonblock()就是为了。考虑到错误代码 11 EWOULDBLOCK, 和 115,的特殊含义,您的套接字交互代码需要以不同方式编写EINPROGRESS。
Here's some somewhat-fictionalized sample code from a PHP sync socket polling loop, as requested:
以下是一些来自 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);
回答by Vladislav Rastrusny
How do I do the same asynchronously? so I can respond to data in a data received event, instead of polling for data, etc.
我如何异步执行相同的操作?所以我可以在数据接收事件中响应数据,而不是轮询数据等。
You will need to execute your script and issue stream_select to check weither there is any data to receive. Process and send data back.
您需要执行脚本并发出 stream_select 以检查是否有任何数据要接收。处理并发回数据。
回答by JSON
The term "asynchronous" is often misused in network programming. For I/O, asynchronous is often just used as another word for non-blocking. This means that the process is able to continue before a call on the network api has completed transmission.
术语“异步”在网络编程中经常被误用。对于 I/O,异步通常只是作为非阻塞的另一种说法。这意味着该过程能够在网络 api 上的调用完成传输之前继续。
For process execution in general, asynchronous means that multiple instructions are able to be computed at once (concurrently.)
对于一般的流程执行,异步意味着能够一次(同时)计算多条指令。
In other words, asynchronous I/O is not truly asynchronous unless multiple threads are used to allow multiple reads/write/accepts to occur concurrently - all sockets will sill have to wait on a synchronous non-blocking call if it has data to be read/written or will otherwise not block, and reading/writing a large file can still take seconds or even minutes if not interrupted. Note that this would require a perfect flow between the client and server or TCP itself will interrupt the transmission. For example, a server sending faster than a client can download would cause a block on a write.
换句话说,除非使用多个线程来允许多个读/写/接受并发发生,否则异步 I/O 并不是真正的异步——如果有数据要读取,所有套接字将不得不等待同步非阻塞调用/written 否则不会阻塞,如果不中断,读取/写入大文件仍然需要几秒钟甚至几分钟。请注意,这将需要客户端和服务器之间的完美流量,否则 TCP 本身会中断传输。例如,服务器发送速度快于客户端下载速度会导致写入阻塞。
So from a strict point of view PHP is not able to perform asynchronous networking, only non-blocking. In short, the progression of the process will stop while the network call is able to usefully read/write etc. However, the process will then continue when the call is not able to usefully read/write or would otherwise block. In a truly asynchronous system the process will continue regardless, and the read/write will be done in a different thread. Note that blocking I/O can still be done asynchronously if done in a different thread.
所以严格来说PHP是不能执行异步联网的,只能是非阻塞的。简而言之,当网络调用能够有效地读/写等时,进程的进展将停止。然而,当调用不能有效地读/写或以其他方式阻塞时,进程将继续。在真正的异步系统中,进程将继续进行,读/写将在不同的线程中完成。请注意,如果在不同的线程中完成,阻塞 I/O 仍然可以异步完成。
Moreover, PHP is not able to do event driven I/O without installing an extension that supports it. You will otherwise need to do some form of polling in order to do non-blocking I/O in PHP. The code from Chaos would be a functional non-blocking read example if it used socket_select.
此外,如果不安装支持事件驱动的 I/O,PHP 将无法执行事件驱动的 I/O。否则,您将需要进行某种形式的轮询,以便在 PHP 中进行非阻塞 I/O。如果使用 socket_select,来自 Chaos 的代码将是一个功能性非阻塞读取示例。
With that said, the select function will still allow true non-blocking behavior in PHP. In C, polling services have a performance loss over event driven, so I'm sure that it would be the same for PHP. But this loss is in the nanoseconds-microseconds depending on the amount of sockets, where the time saved from a non-blocking call is typically milliseconds, or even seconds if the call is made to wait.
话虽如此,select 函数仍将允许 PHP 中真正的非阻塞行为。在 C 中,轮询服务比事件驱动有性能损失,所以我确信 PHP 也是如此。但是这种损失以纳秒-微秒为单位,具体取决于套接字的数量,其中从非阻塞调用中节省的时间通常为毫秒,如果调用等待,则甚至为秒。
回答by MGriesbach
AFAIK PHP is strictly singlethreaded, which means you can't do this asynchronously, because Script execution is always linear.
AFAIK PHP 是严格单线程的,这意味着您不能异步执行此操作,因为脚本执行始终是线性的。
It's been a while since i have done this, but as far as i recall, you can only open the socket, and have the script continue execution upon receiving data.
我已经有一段时间没有这样做了,但据我所知,您只能打开套接字,并让脚本在接收到数据后继续执行。

