zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    前端下拉复选框的使用(这里只有讲述新增时获取值以及查看详情时对他进行赋值)
    layui实现图片上传
    WPF中DataGrid前面加上序号
    Excel导出时出现字符串转换为日期
    redis基础
    Redis安装与集群搭建
    ngnix在Linux下的安装与使用
    redis面试题
    redis持久化的几种方式
    理解乐观锁与悲观锁
  • 原文地址:https://www.cnblogs.com/AUOONG/p/2796090.html
Copyright © 2011-2022 走看看