百度空间 | 百度首页 
 
查看文章
 
Linux下PHP socket问题
2009-10-09 23:09
        因为一些原因,花了一天时间将原来的基于XML-RPC的调用改为直接通过TCP协议完成,不再走HTTP协议(不再使用繁重的XML通讯,采用phpserializer 传输)。服务基于MINA,实现特定的Codec也不困难,但最麻烦的事情在于:在Linux下,读取一个socket中的内容,无论是采用 fread($sock, 4096) 还是 stream_socket_recvfrom($sock, 4096) 在Linux (Windows没问题)下都不能保证正确的读出指定长度(4096byte)。也就是说:

function readSocket($socket)
{
$str = '';
do
{
$l = stream_socket_recvfrom($socket, 4096);
$str .= '';
}
while (strlen($socket) === 4096);
return $str;
}

是无法正确的读出所有的返回内容的,在非Windows 系统下(Linux以及Mac OS), 每次 stream_socket_recvfrom或者fread从socket读出的内容长度是固定的若干种值,在我的测试机上1460以及2000是常出现的情况。当然:
function readSocket($socket)
{
$str = '';
while($l = stream_socket_recvfrom($socket, 4096))
{
$str .= $l;
}
return $str;
}
这个函数则更加糟糕,它会导致整个程序挂起,一直处于等待中,直到等到服务器端设置的Idle时限为止。出现这种状况的原因是,当最后一次stream_socket_recvfrom 或者 fread 的时候,如果缓冲区里真的没有内容的话(期望 stream_socket_recvfrom 读出空),这个函数调用会挂起,等待缓冲区填充内容以完成这次读取(也就是说,退出的条件本身不太可能发生,永远到不了头)。

stream_set_blocking($socket, false) 则是更糟糕的。它将直接导致 stream_socket_recvfrom无论缓冲区里有没有内容,都直接返回。基本上,如果采用这种模式的话,发送请求后,立即从 socket 里读取的话,结果都是空。

注意 stream_socket_recvfrom($socket, 4096, STREAM_OOB) 、stream_socket_recvfrom($socket, 4096) 、stream_socket_recvfrom($socket, 4096, STREAM_PEEK) 的区别。

最后,和ProtocolDecoder 一样,在ProtocolEncoder中在编码数据的末尾添加特定的标志(传输的内容中不肯能出现的控制字符,方向键),客户端检测该标志解决此问题。

类别:Php | 添加到搜藏 | 浏览() | 评论 (0)
 
最近读者:
 
网友评论:
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码: 请点击后输入四位验证码,字母不区分大小写
      

     

©2009 Baidu