FSock.php
4.58 KB
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<?php namespace common\exts\wechat;
/**
* 异步请求类
* 实现效果是: 触发一个PHP脚本,然后立即返回,留它在服务器端慢慢执行
* 注意: 确保php.ini allow_url_fopen=on
* Class FSock
* @package common\exts\wechat
*/
class FSock
{
const DEFAULT_PORT = 80; // 默认端口号
const DEFAULT_TIMEOUT = 30; // 默认请求超时(秒)
const DEFAULT_HTTPS_PORT = 443; //默认https端口号
/**
* 非阻塞式的异步GET请求
* @param string $url http://mall1.mkmart.com/wechat/send 完整url地址(不要携带query参数)
* @param array $param
* sample: $params = array('key1'=>$value1, 'key2'=>$value2);
* @return bool|mixed
*/
public static function get($url, $param = array())
{
//set_time_limit(0); // 暂时默认30秒足够了
$url_array = parse_url($url); // 获取URL信息,以便拼凑HTTP HEADER
$host = $url_array['host'];
$browserHost = $url_array['host'];
$defaultPort = self::DEFAULT_PORT;
if(stripos($url,"https://") !== FALSE){
$host = "ssl://".$host;
$defaultPort = self::DEFAULT_HTTPS_PORT;
}
$port = isset($url_array['port'])? $url_array['port'] : $defaultPort;
$path = $url_array['path'] ."?". http_build_query($param); // 注意: query参数从$param统一传入
$useragent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'; // 默认用户代理(浏览器信息)
if(isset($_SERVER['HTTP_USER_AGENT'])) {
$useragent = $_SERVER['HTTP_USER_AGENT'];
}
Log::init();
//Log::DEBUG('非阻塞式的异步GET请求: host=' . $host . ', path=' . $path . ', port=' . $port);
$fp = @fsockopen($host, $port, $errno, $errstr, self::DEFAULT_TIMEOUT);
if (!$fp) {
Log::ERROR("{$host}{$path}:{$port} {$errstr} ({$errno})<br />\r\n");
return false;
}
stream_set_blocking($fp, 0);//非阻塞模式
$header = "GET {$path} HTTP/1.1\r\n";
$header .= "Host: $browserHost\r\n";
$header .= "User-Agent: " . $useragent . "\r\n"; // 注意: apache服务器需要设置, nginx服务器不需要
$header .= "Connection: Close\r\n\r\n";//长连接关闭
fwrite($fp, $header);
/*
$result = '';
while (!feof($fp)) {
$result .= fgets($fp, 128);
}
*/
fclose($fp);
//Log::DEBUG('非阻塞式的异步GET result = '. $result);
return true;
}
/**
* 非阻塞式的异步POST请求
* @param string $url http://mall1.mkmart.com/wechat/send 完整url地址
* @param array $param
* sample: $params = array('key1'=>$value1, 'key2'=>$value2);
*/
public static function post($url, $param = array())
{
//set_time_limit(0); // 暂时默认30秒足够了
$url_array = parse_url($url); // 获取URL信息,以便拼凑HTTP HEADER
$host = $url_array['host'];
$browserHost = $url_array['host'];
$defaultPort = self::DEFAULT_PORT;
if(stripos($url,"https://") !== FALSE){
$host = "ssl://".$host;
$defaultPort = self::DEFAULT_HTTPS_PORT;
}
$port = isset($url_array['port'])? $url_array['port'] : $defaultPort;
$path = $url_array['path'];
$data = http_build_query($param); // POST数据
$useragent = 'chrome'; // 默认用户代理(浏览器信息)
if(isset($_SERVER['HTTP_USER_AGENT'])) {
$useragent = $_SERVER['HTTP_USER_AGENT'];
}
Log::init();
//Log::DEBUG('非阻塞式的异步POST请求: host=' . $host . ', path=' . $path . ', port=' . $port);
$fp = fsockopen($host, $port, $errno, $errstr, self::DEFAULT_TIMEOUT);
if (!$fp) {
Log::ERROR("$errstr ($errno)<br />\n");
return false;
}
// 设置非阻塞模式
stream_set_blocking($fp, 0);
$out = "POST $path HTTP/1.1\r\n";
$out .="Host: $browserHost\r\n";
$out .= "User-Agent: " . $useragent . "\r\n"; // 注意: apache服务器需要设置, nginx服务器不需要
$out .= "Content-Type: application/x-www-form-urlencoded\r\n"; // POST数据
$out .= "Content-Length: ". strlen($data) ." \r\n"; // POST数据的长度
$out .="Connection: Close\r\n\r\n";//长连接关闭
$out .= $data; // 传递POST数据
fwrite($fp, $out);
fclose($fp);
//Log::DEBUG('非阻塞式的异步POST请求: out=' . $out);
return true;
}
}