前戏
如果我想用php实现一个http异步请求,是否能做到呢?
正题
答案是肯定的,以下是我的socket解决方案:
function makeRequestAsync($url, $params = array(), $type='POST')
{
$query_string = '';
if(is_array($params) && !empty($params))
$query_string = http_build_query($params);
elseif(is_string($params))
$query_string = $params;
$type = strtoupper($type);
$parts=parse_url($url);
$fp = fsockopen($parts['host'], isset($parts['port']) ? $parts['port'] : 80, $errno, $errstr, 1);
if('GET' == $type) $parts['path'] .= '?'.$query_string;
$out = "$type ".$parts['path']." HTTP/1.1\r\n";
$out.= "Host: ".$parts['host']."\r\n";
$out.= "Content-Type: application/x-www-form-urlencoded\r\n";
if ('POST' == $type) $out.= "Content-Length: ".strlen($query_string)."\r\n";
$out.= "Connection: Close\r\n\r\n";
if ('POST' == $type && isset($query_string)) $out.= $query_string;
fwrite($fp, $out);
stream_set_timeout($fp, 1);
fclose($fp);
}
测试
测试方法:
client.php
makeRequestAsync('http://127.0.0.1/async/server.php');
makeRequestAsync('http://127.0.0.1/async/server.php');
makeRequestAsync('http://127.0.0.1/async/server.php');
makeRequestAsync('http://127.0.0.1/async/server.php');
makeRequestAsync('http://127.0.0.1/async/server.php');
makeRequestAsync('http://127.0.0.1/async/server.php');
echo 'done';
server.php
sleep(6);
file_put_contents(uniqid(), '');
echo 'x';
用浏览器打开client.php看到瞬间执行完毕,但async目录里面需要6秒后才会生成文件,成功了。
多说两句
这里需要注意两个地方,一个是fsockopen的超时时间,这个时间需要设置得小一点,如果一个ip是无法访问到的,并且超时时间很长的话,这个socket连接需要等到过了这个超时时间才会执行后续代码。这样会导致代码卡死。另外这个方法是否无法处理server端的返回的。
另一个是stream流的超时时间,也就是fwrite流的超时时间stream_set_timeout,这个也需要设置小一点,我这里将两个超时时间都设置成了1秒。实际运用中可能需要设置成更小的值。
所以这个方法也是有缺陷的,就是可能会丢失数据,有请求超时的风险。
如果您觉得您在我这里学到了新姿势,博主支持转载,姿势本身就是用来相互学习的。同时,本站文章如未注明均为 hisune 原创 请尊重劳动成果 转载请注明 转自: php的异步http请求解决方案 - hisune.com
0 Comments