2012-07-04 62 views
0

基本上,我使用的是socket_accept()沿阻挡 TCP套接字。我遇到的问题是,由于显而易见的原因,因为I/O被阻塞,PHP可以在任何时候只能有一个连接到套接字。我对此很好,因为这是我所追求的行为。但是,如果客户端要打开一个到我的PHP服务器的连接,如果他们只是简单地将套接字打开并且不发送数据,那么套接字和守护进程就会变得无用,因为阻塞I/O不会允许新的要求。PHP的Socket阻塞

有没有一种方法可以检测客户端是根本没有发送任何数据(如无传输超时)或类似的东西?我宁愿不使用非阻塞I/O。

+0

请出示你的主循环 - 主要是您阻塞调用。 (例如'$海峡=与fgets($袜子);') – DaveRandom

+0

http://ss.totalru.in/I5NG – Blake

+0

这是失踪的我的代码的其余部分,因为它是非常广泛的,但是这是正在使用socket_read是哪里。值得注意的是套接字也在socket_close的循环中关闭。 – Blake

回答

1

你可以简单地调用the equivalent ofstream_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"; 

注意,这是一个黑客攻击;恶意攻击者仍然可以每秒只发送1个字节左右。

而是投资于这些疯狂的黑客时,你真的应该切换到非阻塞IO或在一个单独的线程/进程处理接受的套接字。

+0

发送一个字节会导致socket_read()触发吗?或者它仍然会继续等待数据的结束? – Blake

+0

不,'socket_read'会正常启动。但是你的应用程序可能会继续阅读。除非你正在构建一个一次性的脚本,我强烈建议使用适当的非阻塞套接字和['socket_select'(http://php.net/manual/en/function.socket-select.php) – phihag