fsockopen开打很慢的原因-完善DZ的dfopen函数

来源:互联网 发布:哭 知乎 编辑:程序博客网 时间:2024/05/29 17:09
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
function dfopen($url$post ''$limit = 0,  $cookie ''$bysocket = FALSE, $ip ''$timeout = 15, $block = TRUE) {
    $return '';
    $uri parse_url($url);
    $host $uri['host'];
    $path $uri['path'] ? $uri['path'].($uri['query'] ? '?'.$uri['query'] : '') : '/';
    $port = !empty($uri['port']) ? $uri['port'] : '';
    if(!$port){
        $port = ($uri['scheme'] == 'https') ? 80 : 80;
    }
    if($post) {//post请求
        $post = http_build_query($post);
        $out "POST $path HTTP/1.0\r\n";
        $out .= "Accept: */*\r\n";
        //$out .= "Referer: $boardurl\r\n";
        $out .= "Accept-Language: zh-cn\r\n";
        $out .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $out .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
        $out .= "Host: $host\r\n";
        $out .= 'Content-Length: '.strlen($post)."\r\n";
        $out .= "Connection: Close\r\n";
        $out .= "Cache-Control: no-cache\r\n";
        $out .= "Cookie: $cookie\r\n\r\n";
        $out .= $post;       
    else {//get请求
        $out "GET $path HTTP/1.0\r\n";
        $out .= "Accept: */*\r\n";
        //$out .= "Referer: $boardurl\r\n";
        $out .= "Accept-Language: zh-cn\r\n";
        $out .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
        $out .= "Host: $host\r\n";
        $out .= "Connection: Close\r\n";
        $out .= "Cookie: $cookie\r\n\r\n";
    }
      
    $fp = @fsockopen(($ip $ip $host), $port$errno$errstr$timeout);
    if(!$fp) {
        return false;//note $errstr : $errno \r\n
    else {
        //集阻塞/非阻塞模式流,$block==true则应用流模式
        stream_set_blocking($fp$block);
        //设置流的超时时间
        stream_set_timeout($fp$timeout);
        @fwrite($fp$out);
        //从封装协议文件指针中取得报头/元数据
        $status = stream_get_meta_data($fp);
  
        //timed_out如果在上次调用 fread() 或者 fgets() 中等待数据时流超时了则为 TRUE,下面判断为流没有超时的情况
        if(!$status['timed_out'])
        {
            while (!feof($fp)) {
                $header = @fgets($fp);
                $findstr 'Content-Length:';
                if(strpos($header$findstr) !== false){//获取内容长度
                    $limit intval(substr($headerstrlen($findstr)));
                }
                if($header == "\r\n" ||  $header == "\n") {
                    break;
                }
            }
            $stop = false;
              
            //如果没有读到文件尾
            while(!feof($fp) && !$stop) {
                //看连接时限是否=0或者大于8192  =》8192  else =》limit  所读字节数
                $data fread($fp, ($limit == 0 || $limit > 8192 ? 8192 : $limit));
                $return .= $data;
                if($limit) {
                    $limit -= strlen($data);
                    $stop $limit <= 0;
                }
            }
        }
        @fclose($fp);
        return $return;
    }
}

业务需要,使用fsockopen模拟get/post的请求去获取数据,
在网上找了下封装好的方法,看DZ封装的那个函数还不错,就拿来使用了。代码如下:有的地方我修改过了


开始测试了一下,就是运行会很慢,需要10几秒的时间才能运行完毕。
但是用file_get_contents的话,很快就能取到数据。
排查了一下,应该是对方的服务器保持活动链接,然后又因为我取数据的时候用到了
!feof($fp),这个地方跟那个指定的获取的长度有关,也就是$limit,如果这个值越大,
他就会一直找下去,只到找到换行符。
最好的办法就是再加个获取内容长度的代码,这样就避免的长时间的等待。
修改的代码主要是这一块

1
2
3
4
5
6
7
8
9
10
while (!feof($fp)) {
    $header = @fgets($fp);
    $findstr 'Content-Length:';
    if(strpos($header$findstr) !== false){//获取内容长度
        $limit intval(substr($headerstrlen($findstr)));
    }
    if($header == "\r\n" ||  $header == "\n") {
        break;
    }
}


OK,好了。测试通过了。

原创粉丝点击