PHP中使用socket通信响应速度慢的原因与解决办法

在PHP中作为客户端与服务器端使用socket进行通信时,一般我们使用fsockopen,但在使用这个函数进行通信时,有时候发现数据的反应时间特别长,更有甚者能达到1分钟。以下是代码片段:

 1 <?php
 2 
 3 function send($data /* String */) {
 4     $result = '';
 5     
 6     $fp = fsockopen($this->url, $this->port, $errno, $errstr, 10);
 7     
 8     if (!$fp) {
 9         return null;
10     } else {
11         fputs($fp, $this->method." ".$this->uri." HTTP/1.1\r\n");
12         fputs($fp, "Host: ".$this->url.":".$this->port."\r\n");
13         fputs($fp, "Content-type: text/html;charset=".$this->charset."\r\n");
14         fputs($fp, "Accept-Language: zh-cn\r\n");
15         fputs($fp, "User-Agent: Mozilla/4.0(Compatible win32; MSIE)\r\n");
16         fputs($fp, "Content-Length: ".strlen($data)."\r\n");
17         fputs($fp, "Connection: close\r\n\r\n");
18         fputs($fp, $data);
19         
20         while(!feof($fp)) {
21             $result .= fgets($fp, 1024);
22         }
23         
24         fclose($fp);
25         
26         $arr = split("\r\n", $result);
27         $state = split(" ", $arr[0]);
28         
29         if (substr($state[1], 0, 1) != 2) {
30             return null;
31         } else {
32             return substr($result, strpos($result, "\r\n\r\n") + 4);
33         }
34     }
35 }

上面这段代码就会有时候出现数据响应时间特别长。经过调试发现问题出在fgets这个函数的返回上,最后一次数据返回的时间很长,说是数据返回不如说是服务器端因为超时断开了连接。经过查阅手册会发现,关于fgets的返回的条件为:碰到换行符(包括在返回值中)、EOF 或者已经读取了 length - 1 字节后停止(看先碰到那一种情况)。

问题就出在服务器端缓冲会话的时候是不会返回结束标志,也不返回换行符的情况。那么我们可以通过以下方法来解决这个问题。

设置一个返回长度$length = 1024。第一次时使用这个长度,当有数据返回时,取出数据的长度$len,然后根据返回的数据来计算还有多少剩余的数据,这样就可以根据$length与(剩余的长度+1)找出最小值$min。下次fgets时的返回长度修正为$min。这样就可以正常的判断返回数据的大小。部分代码如下:

 1 <?php
 2 function send($data /* String */) {
 3     $result = '';
 4     
 5     $fp = fsockopen($this->url, $this->port, $errno, $errstr, 10);
 6     
 7     if (!$fp) {
 8         return null;
 9     } else {
10         fputs($fp, $this->method." ".$this->uri." HTTP/1.1\r\n");
11         fputs($fp, "Host: ".$this->url.":".$this->port."\r\n");
12         fputs($fp, "Content-type: text/html;charset=".$this->charset."\r\n");
13         fputs($fp, "Accept-Language: zh-cn\r\n");
14         fputs($fp, "User-Agent: Mozilla/4.0(Compatible win32; MSIE)\r\n");
15         fputs($fp, "Content-Length: ".strlen($data)."\r\n");
16         fputs($fp, "Connection: close\r\n\r\n");
17         fputs($fp, $data);
18         
19         $len    = -1;
20         $length = 1024;
21         while(!feof($fp)) {
22             $result .= fgets($fp, $length);
23             
24             if (stripos($result, "\r\n\r\n") !== false) {
25                 $start = stripos($result, "Content-Length:") + 15;
26                 
27                 if ($start !== false && $len < 0) {
28                     $end = stripos($result, "\r\n", $start);
29                     $len = trim(substr($result, $start, stripos($result, "\r\n", $start) - $start));
30                 }
31                 
32                 if ($len > 0) {
33                     $str = substr($result, strpos($result, "\r\n\r\n") + 4);
34                     $length = min($length, $len - strlen($str) + 1);
35                 }
36                 
37                 if ($length < 2) {
38                     fclose($fp);
39                     return $str;
40                 }
41             }
42         }
43     }
44 }
posted @ 2012-11-30 13:23  AUOONG  阅读(1269)  评论(0编辑  收藏  举报