curl — PHP CLI, пишущий и читающий несколько сырых tcp API параллельно, как curl_multi_init для https API

Моя ситуация:

У меня есть несколько серверов, использующих сырой TCP API, который требует от меня отправки строки для получения информации от них. Мне нужно получить ответ в течение 5 секунд. Все API должны связываться одновременно, и с этого момента у них есть 5 секунд, чтобы ответить. (Таким образом, максимальное время выполнения составляет 5 секунд для всех серверов одновременно)

Мне уже удалось сделать это для HTTP / S API с PHP cURL:

// array of curl handles
$multiCurl = array();
// data to be returned
$result = array();
// multi handle
$mh = curl_multi_init();
foreach ($row_apis as $api) {
$id = $api[0];
$ip = $api[1];
$port = $api[2];
// URL from which data will be fetched
$fetchURL = "$ip:$port/api/status";
$multiCurl[$id] = curl_init();
curl_setopt($multiCurl[$id], CURLOPT_URL,$fetchURL);
//curl_setopt($multiCurl[$id], CURLOPT_HEADER,0);
curl_setopt($multiCurl[$id], CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_1);
curl_setopt($multiCurl[$id], CURLOPT_CUSTOMREQUEST,"GET");
curl_setopt($multiCurl[$id], CURLOPT_TIMEOUT,5);
curl_setopt($multiCurl[$id], CURLOPT_RETURNTRANSFER,1);
curl_multi_add_handle($mh, $multiCurl[$id]);
}
$index=null;
do {
curl_multi_exec($mh,$index);
} while($index > 0);
// get content and remove handles
foreach($multiCurl as $k => $ch) {
$result[$k] = json_decode(curl_multi_getcontent($ch), true);
curl_multi_remove_handle($mh, $ch);
}
// close
curl_multi_close($mh);

Этот пример извлекает все API одновременно и ждет 5 секунд для восстановления. Это никогда не займет больше 5 секунд.

Есть ли способ сделать то же самое с необработанными TCP API в PHP?
Я уже пытался использовать сокеты и смог получить информацию, но каждый API выбирается один за другим, поэтому сценарий становится длинным для нескольких серверов.

Спасибо за вашу помощь.

РЕДАКТИРОВАТЬ:

Я попытался реализовать ваши предложения, и мой код теперь выглядит так:

$apis = array();
$apis[0] = array(1, "123.123.123.123", 1880);

$method = "summary";
$sockets = array();

//Create socket array
foreach($apis as $api){
$id = $api[0];
$ip = $api[1];
$port = $api[2];

$sockets[$id] = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_nonblock($sockets[$id]);
@socket_connect($sockets[$id], $ip, $port);
//socket_write($sockets[$id], $method);
}

//Write to every socket
/*
foreach($sockets as $socket){
socket_write($socket, $method);
//fwrite($socket, "$method");
}
*/

//Read all sockets for 5 seconds
$write  = NULL;
$except = NULL;
$responses = socket_select($sockets, $write, $except, 5);

//Check result
if($responses === false){
echo "Did not work";
}
elseif($responses > 0){
echo "At least one has responded";
}

//Access the data
//???

Но я получаю 0 в результате socket_select …
Когда мне нужно записать метод в сокет?
И если я получу что-то обратно, как мне получить доступ к данным, которые были в ответе?

1

Решение

абсолютно. задавать SO_SNDBUF до соответствующего размера, так что вы можете отправить все запросы мгновенно / без блокировки, затем отправить все запросы, а затем начать ожидание / чтение ответов.

Самый простой способ сделать это — позвонить socket_set_block на сокетах и ​​прочитайте все ответы 1 на 1, но это не дает точной гарантии 5-секундного тайм-аута (но опять же, как и ваш пример кода curl_multi), если вам нужен 5-секундный тайм-аут, используйте socket_set_nonblock & socket_select вместо.

0

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector