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
(
$header
,
strlen
(
$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
(
$header
,
strlen
(
$findstr
)));
}
if
(
$header
==
"\r\n"
||
$header
==
"\n"
) {
break
;
}
}
|
OK,好了。测试通过了。