PHP CLI并行编写和读取多个原始tcp API,如curl_multi_init for https API' s

时间:2018-04-10 14:15:47

标签: php curl tcp client

我的情况:

我有多台服务器运行原始TCP API,要求我发送字符串以从中获取信息。我需要在5秒的超时内得到响应。应该同时联系所有API,从那里他们有5秒的时间来回复。 (因此,所有服务器的最大执行时间一次为5秒)

我已经设法使用PHP cURL来实现HTTP / S API:

// 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秒。

有没有办法在PHP中使用原始TCP API执行相同的操作? 我已经尝试使用套接字并且能够获取信息,但是每个API都是在另一个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
//???

但是我因为socket_select而得到0 ... 我什么时候需要将方法写入套接字? 如果我得到回复,我该如何访问响应中的数据?

1 个答案:

答案 0 :(得分:0)

绝对。将SO_SNDBUF设置为适当的大小,以便您可以立即/非阻塞地发送所有请求,然后发送所有请求,然后开始等待/读取响应。

执行读取的简单方法是在套接字上调用socket_set_block,并逐个读取所有响应,但这并不能保证5秒超时(但是再次,您的示例curl_multi代码),如果您需要5秒超时,请使用socket_set_nonblock&而是socket_select