PHP 具有不同端口的多卷曲
PHP Multi curl with different ports
我正在使用物联网系统并尝试改进我们的数据摄取。目前我们正在遍历一组具有不同端口的 URL 并一次发送一个 curl 请求。我想使用 multicurl 来绕过这个瓶颈,但我只收到错误作为响应。
这是我的代码(已编辑 IP 地址)
$url = 'http://XXX.XXX.XX.XXX/getvar.csv';
$ports = [8101,8102,8103,8104];
foreach ($ports as $port) {
$worker = curl_init($curl_url);
curl_setopt_array($worker, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HEADER => 0,
CURLOPT_TIMEOUT => 8,
CURLOPT_POSTFIELDS => $content,
CURLOPT_PORT => $port
]);
curl_multi_add_handle($mh, $worker);
}
$i=0;
for (; ;) {
$still_running = null;
echo "<p>exec multi curl $i</p>";
do {
echo "<p>curl multi exec</p>";
$err = curl_multi_exec($mh, $still_running);
} while ($err === CURLM_CALL_MULTI_PERFORM);
if ($err !== CURLM_OK) {
$description = curl_strerror(curl_errno($mh));
echo "<p>Error description: $description</p>";
// handle curl multi error?
}
if ($still_running < 1) {
echo "<p>curl multi finished</p>";
// all downloads completed
break;
}
// some haven't finished downloading, sleep until more data arrives:
curl_multi_select($mh, 8);
$i++;
}
$curl_time_stop = microtime(true);
$curl_duration += $curl_time_stop - $curl_time_start;
echo "CURL finished";
$results = [];
while (false !== ($info = curl_multi_info_read($mh))) {
if ($info["result"] !== CURLE_OK) {
echo "Error ".curl_strerror($info["result"]);
// handle download error?
}
$results[curl_getinfo($info["handle"], CURLINFO_EFFECTIVE_URL)] =
curl_multi_getcontent($info["handle"]);
curl_multi_remove_handle($mh, $info["handle"]);
curl_close($info["handle"]);
}
curl_multi_close($mh);
var_dump($results);
这是我得到的errors/response
Error Server returned nothing (no headers, no data)
results int(1) int(52) resource(29) of type (curl)
据我所知,错误代码 52 对应于 CURLE_GOT_NOTHING
。
有什么我想念的吗?或者 multi-curl 与 curl 使用的协议有区别吗?
[编辑:添加详细输出]
这是我使用 CURLOPT_VERBOSE=>1
时的结果
* Trying 1XX.XX.XX.XX:8101...
* Found bundle for host 1XX.XX.XX.XX: 0x2625a00 [serially]
* Server doesn't support multiplex (yet)
* Hostname 1XX.XX.XX.XX was found in DNS cache
* Trying 1XX.XX.XX.XX:8101...
*** Connected to 1XX.XX.XX.XX (1XX.XX.XX.XX) port 8101 (#0)
> POST /getvar.csv? HTTP/1.1
Host: 1XX.XX.XX.XX:8101
Accept: */*
Content-Length: 248
Content-Type: application/x-www-form-urlencoded**
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: text/csv; charset="utf-8"
< Server: embedded HTTPD
< Expires: 1 JAN 2013 00:00:00 GMT
< Last-Modified: 4 MAR 2021 12:10:09 GMT
< Cache-Control: no-cache
< Transfer-Encoding: chunked
* Connection #0 to host 1XX.XX.XX.XX left intact
* Empty reply from server
* Closing connection 25
我发现我的代码存在外部问题,但我将最终的工作代码发布在此处以供将来参考。
Multi-curl 不喜欢遍历端口号,所以我不得不将端口烘焙到 curl URL 中并遍历 URL 的数组。
$content
不是 multicurl 工作所必需的,但它是从我正在调用的 URL 中获取数据。
<?php
$lists=[
"LocalBoardTemp"
];
$url = 'http://XXX.XXX.XXX.XXX:';
$ports = [8101,8102,8103,8104,8105,8106,8107,8108,8109];
foreach ($ports as $port) {
$curl_urls[] = $url.$port.'/getvar.csv?';
}
$content = '';
foreach ($lists as $list1) {
$content = $content . "&name=" . $list1;
}
$mh = curl_multi_init();
$fp = fopen(dirname(__FILE__).'/curl_errorlog.txt', 'w');
$i=0;
foreach ($curl_urls as $url) {
$worker = curl_init($url);
curl_setopt_array($worker, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HEADER => 0,
CURLOPT_TIMEOUT => 8,
CURLOPT_POSTFIELDS => $content,
CURLOPT_VERBOSE=>1,
CURLOPT_STDERR => $fp
// ,
// CURLOPT_PORT => $port
]);
curl_multi_add_handle($mh, $worker);
}
for (; ;) {
$still_running = null;
echo "<p>exec multi curl $i</p>";
do {
echo "<p>curl multi exec</p>";
$err = curl_multi_exec($mh, $still_running);
} while ($err === CURLM_CALL_MULTI_PERFORM);
if ($err !== CURLM_OK) {
$description = curl_strerror(curl_errno($mh));
echo "<p>Error description: $description</p>";
// handle curl multi error?
}
if ($still_running < 1) {
echo "<p>curl multi finished</p>";
// all downloads completed
break;
}
// some haven't finished downloading, sleep until more data arrives:
curl_multi_select($mh, 8);
$i++;
}
echo "CURL finished";
$results = [];
$j = 0;
while (false !== ($info = curl_multi_info_read($mh))) {
if ($info["result"] !== CURLE_OK) {
echo "Error ".curl_strerror($info["result"]);
// handle download error?
}
echo "<p>results ";
foreach ($info as $x) {
var_dump($x);
}
echo "</p>";
$results[curl_getinfo($info["handle"], CURLINFO_EFFECTIVE_URL)] = curl_multi_getcontent($info["handle"]);
echo "<p>result index $j". curl_multi_getcontent($info["handle"])."</p>";
curl_multi_remove_handle($mh, $info["handle"]);
curl_close($info["handle"]);
$j++;
}
curl_multi_close($mh);
echo "<p>All results dump: ";
var_dump($results);
echo "</p>";
fclose($fp);
echo "finished";
这是从几个教程和堆栈溢出答案中拼凑而成的,所以我确信有一种更有效的方法可以做到这一点,但它确实有效。
我正在使用物联网系统并尝试改进我们的数据摄取。目前我们正在遍历一组具有不同端口的 URL 并一次发送一个 curl 请求。我想使用 multicurl 来绕过这个瓶颈,但我只收到错误作为响应。 这是我的代码(已编辑 IP 地址)
$url = 'http://XXX.XXX.XX.XXX/getvar.csv';
$ports = [8101,8102,8103,8104];
foreach ($ports as $port) {
$worker = curl_init($curl_url);
curl_setopt_array($worker, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HEADER => 0,
CURLOPT_TIMEOUT => 8,
CURLOPT_POSTFIELDS => $content,
CURLOPT_PORT => $port
]);
curl_multi_add_handle($mh, $worker);
}
$i=0;
for (; ;) {
$still_running = null;
echo "<p>exec multi curl $i</p>";
do {
echo "<p>curl multi exec</p>";
$err = curl_multi_exec($mh, $still_running);
} while ($err === CURLM_CALL_MULTI_PERFORM);
if ($err !== CURLM_OK) {
$description = curl_strerror(curl_errno($mh));
echo "<p>Error description: $description</p>";
// handle curl multi error?
}
if ($still_running < 1) {
echo "<p>curl multi finished</p>";
// all downloads completed
break;
}
// some haven't finished downloading, sleep until more data arrives:
curl_multi_select($mh, 8);
$i++;
}
$curl_time_stop = microtime(true);
$curl_duration += $curl_time_stop - $curl_time_start;
echo "CURL finished";
$results = [];
while (false !== ($info = curl_multi_info_read($mh))) {
if ($info["result"] !== CURLE_OK) {
echo "Error ".curl_strerror($info["result"]);
// handle download error?
}
$results[curl_getinfo($info["handle"], CURLINFO_EFFECTIVE_URL)] =
curl_multi_getcontent($info["handle"]);
curl_multi_remove_handle($mh, $info["handle"]);
curl_close($info["handle"]);
}
curl_multi_close($mh);
var_dump($results);
这是我得到的errors/response
Error Server returned nothing (no headers, no data)
results int(1) int(52) resource(29) of type (curl)
据我所知,错误代码 52 对应于 CURLE_GOT_NOTHING
。
有什么我想念的吗?或者 multi-curl 与 curl 使用的协议有区别吗?
[编辑:添加详细输出]
这是我使用 CURLOPT_VERBOSE=>1
* Trying 1XX.XX.XX.XX:8101...
* Found bundle for host 1XX.XX.XX.XX: 0x2625a00 [serially]
* Server doesn't support multiplex (yet)
* Hostname 1XX.XX.XX.XX was found in DNS cache
* Trying 1XX.XX.XX.XX:8101...
*** Connected to 1XX.XX.XX.XX (1XX.XX.XX.XX) port 8101 (#0)
> POST /getvar.csv? HTTP/1.1
Host: 1XX.XX.XX.XX:8101
Accept: */*
Content-Length: 248
Content-Type: application/x-www-form-urlencoded**
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: text/csv; charset="utf-8"
< Server: embedded HTTPD
< Expires: 1 JAN 2013 00:00:00 GMT
< Last-Modified: 4 MAR 2021 12:10:09 GMT
< Cache-Control: no-cache
< Transfer-Encoding: chunked
* Connection #0 to host 1XX.XX.XX.XX left intact
* Empty reply from server
* Closing connection 25
我发现我的代码存在外部问题,但我将最终的工作代码发布在此处以供将来参考。
Multi-curl 不喜欢遍历端口号,所以我不得不将端口烘焙到 curl URL 中并遍历 URL 的数组。
$content
不是 multicurl 工作所必需的,但它是从我正在调用的 URL 中获取数据。
<?php
$lists=[
"LocalBoardTemp"
];
$url = 'http://XXX.XXX.XXX.XXX:';
$ports = [8101,8102,8103,8104,8105,8106,8107,8108,8109];
foreach ($ports as $port) {
$curl_urls[] = $url.$port.'/getvar.csv?';
}
$content = '';
foreach ($lists as $list1) {
$content = $content . "&name=" . $list1;
}
$mh = curl_multi_init();
$fp = fopen(dirname(__FILE__).'/curl_errorlog.txt', 'w');
$i=0;
foreach ($curl_urls as $url) {
$worker = curl_init($url);
curl_setopt_array($worker, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HEADER => 0,
CURLOPT_TIMEOUT => 8,
CURLOPT_POSTFIELDS => $content,
CURLOPT_VERBOSE=>1,
CURLOPT_STDERR => $fp
// ,
// CURLOPT_PORT => $port
]);
curl_multi_add_handle($mh, $worker);
}
for (; ;) {
$still_running = null;
echo "<p>exec multi curl $i</p>";
do {
echo "<p>curl multi exec</p>";
$err = curl_multi_exec($mh, $still_running);
} while ($err === CURLM_CALL_MULTI_PERFORM);
if ($err !== CURLM_OK) {
$description = curl_strerror(curl_errno($mh));
echo "<p>Error description: $description</p>";
// handle curl multi error?
}
if ($still_running < 1) {
echo "<p>curl multi finished</p>";
// all downloads completed
break;
}
// some haven't finished downloading, sleep until more data arrives:
curl_multi_select($mh, 8);
$i++;
}
echo "CURL finished";
$results = [];
$j = 0;
while (false !== ($info = curl_multi_info_read($mh))) {
if ($info["result"] !== CURLE_OK) {
echo "Error ".curl_strerror($info["result"]);
// handle download error?
}
echo "<p>results ";
foreach ($info as $x) {
var_dump($x);
}
echo "</p>";
$results[curl_getinfo($info["handle"], CURLINFO_EFFECTIVE_URL)] = curl_multi_getcontent($info["handle"]);
echo "<p>result index $j". curl_multi_getcontent($info["handle"])."</p>";
curl_multi_remove_handle($mh, $info["handle"]);
curl_close($info["handle"]);
$j++;
}
curl_multi_close($mh);
echo "<p>All results dump: ";
var_dump($results);
echo "</p>";
fclose($fp);
echo "finished";
这是从几个教程和堆栈溢出答案中拼凑而成的,所以我确信有一种更有效的方法可以做到这一点,但它确实有效。