0

基本上,我使用阻塞TCP 套接字和socket_accept(). 我遇到的问题是,由于明显的原因,由于 I/O 阻塞,在 PHP 能够操作的任何时间都只能有一个到套接字的连接。我对此很好,因为这是我所追求的行为。

但是,如果客户端要打开到我的 PHP 服务器的连接,如果他们只是让套接字保持打开状态并且不发送数据,那么套接字和守护进程将变得无用,因为阻塞 I/O 将不允许新请求。

有没有办法检测一个客户端只是不发送数据(如无传输超时)或类似的东西?我宁愿不使用非阻塞 I/O。

4

2 回答 2

1

您可以简单地调用等价 stream_set_timeout于使阻塞读取和写入在特定超时后终止:

$s = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if (!socket_bind($s, '127.0.0.1', 0)) die("bind failed");
if (!socket_listen($s)) die("listen failed");
socket_getsockname($s, $localA, $localPort);
echo 'Listening on ' . $localA . ': ' . $localPort . "\n";

$c = socket_accept($s);

// Warning: Ugly hack ahead.
// This just mitigates the problem somewhat, and doesn't actually solve it
socket_set_option($c, SOL_SOCKET, SO_RCVTIMEO, array('sec'=>2,'usec'=>0));
socket_set_option($c, SOL_SOCKET, SO_SNDTIMEO, array('sec'=>2,'usec'=>0));

$r = socket_read($c, 1024);
echo 'read finished: got ' . var_export($r, true) . "\n";

请注意,这是一个 hack;恶意攻击者仍然只能每秒发送 1 个字节左右。

与其在这些疯狂的 hack 上花费时间,不如真正切换到非阻塞 IO 或在单独的线程/进程中处理接受的套接字。

于 2012-07-04T10:48:49.887 回答
0

我曾经使用 Tudor Barbu Thread 类为 Websocket 服务器做一些伪线程......

这是一个要点:https ://gist.github.com/eda7d47ec4e475af531e

于 2012-07-04T11:24:17.763 回答