我在curl中遇到了一些非常奇怪的行为
这似乎是libcurl related question中的一个错误,而回答者有一个work around for it。
我的问题是:
$ch = curl_init('https://www.google.ca/');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$success = curl_exec($ch);
var_dump($success !== false); // true
curl_close($ch);
$pid = pcntl_fork();
if ($pid === 0) {
$ch = curl_init('http://www.google.ca/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$success = curl_exec($ch);
var_dump($success !== false); // true
curl_close($ch);
$ch = curl_init('https://www.google.ca/');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$success = curl_exec($ch);
var_dump($success !== false); // false
$errno = curl_errno($ch); // 35
$error = curl_error($ch); // SSL connect error
curl_close($ch);
} else if ($pid > 0) {
// wait for child process
pcntl_wait($status);
} else {
// handel fork error
}
如果这不是libcurl的错误而且我做错了请告诉我。
答案 0 :(得分:1)
我刚刚使用pcntl_exec函数解决了这个问题。所以你基本上会删除你的子代码并将它放在一个不同的php文件中,然后执行(并实际替换)子进程。
public class SomeClass() {
private ISomeService _service;
private IAnotherService _anotherService;
public SomeClass(ISomeService service, IAnotherService anotherService) {
_service = service;
_anotherService = anotherService;
}
}
child_curl.php的内容:
$ch = curl_init('https://www.google.ca/');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$success = curl_exec($ch);
var_dump($success !== false); // true
curl_close($ch);
$pid = pcntl_fork();
if ($pid === 0) {
pcntl_exec('child_curl.php');
} else if ($pid > 0) {
// wait for child process
pcntl_wait($status);
} else {
// handel fork error
}
执行孩子后,你不会看到错误。
这些其他问题帮助了我:
答案 1 :(得分:0)
我还没有找到一种直接处理问题的方法。但是,我已经开发了几个解决方法。两者都解决了进程fork问题(猜猜是什么)另一个fork。
请注意:这不是为了提高性能。这只是问题中突出显示的问题的解决方法。
function fetch_page($page) {
$tmp_file = tempnam(sys_get_temp_dir(), 'curl_tmp_file');
$pid = pcntl_fork();
if ($pid === 0) {
$ch = curl_init($page);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$content = curl_exec($ch);
curl_close($ch);
if ($content) {
file_put_contents($tmp_file, $content);
exit(0);
}
else {
exit(1);
}
}
else if ($pid > 0) {
pcntl_wait($status);
$content = false;
if (pcntl_wexitstatus($status) === 0) {
$content = file_get_contents($tmp_file);
}
unlink($tmp_file);
return $content;
}
else {
unlink($tmp_file);
return false;
}
}
关于我的信可以在子进程中建立https连接。
fetch_page('https://www.google.ca/');
$pid = pcntl_fork();
if ($pid === 0) {
$ch = curl_init('https://www.google.ca/');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$success = curl_exec($ch);
var_dump($success !== false); // true
} else if ($pid > 0) {
// wait for child process
pcntl_wait($status);
} else {
// handel fork error
}
答案 2 :(得分:0)
另一种解决方法是使用套接字。
function fetch_page($url) {
$socketPair = array();
if (socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $socketPair) === false) {
return false;
}
$pid = pcntl_fork();
if ($pid === 0) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$content = curl_exec($ch);
curl_close($ch);
socket_close($socketPair[1]);
socket_set_nonblock($socketPair[0]);
$exitStatus = $content ? 0 : 1;
if ($content) {
while ((strlen($content) > 0) && ($wrote = socket_write($socketPair[0], $content))) {
$content = substr($content, $wrote);
}
}
socket_close($socketPair[0]);
exit($exitStatus);
}
else if ($pid > 0) {
pcntl_wait($status);
socket_close($socketPair[0]);
$content = false;
if (pcntl_wexitstatus($status) === 0) {
$content = '';
while ($line = socket_read($socketPair[1], 4096)) {
$len = strlen($content);
$content .= $line;
}
}
socket_close($socketPair[1]);
return $content;
}
socket_close($socketPair[0]);
socket_close($socketPair[1]);
return false;
}