好的,目标是用“超时”和/或“间隔”来“流式传输SOAP响应”?
我建议覆盖SoapClient __doRequest()方法,并通过fsockopen()实现一个自定义连接,并使用stream_get_contents()流传输数据.
现在你会收到一个XML数据流,你想要的就是它的中间位置.
您必须提取XML信封或其部分内容,可能使用字符串函数或使用preg_match来获取内部内容.
以下代码提供了一个SoapClientTimeout类,其中超时通过stream_set_timeout()设置.这是用例,当服务器响应缓慢,并且您想要确定何时结束侦听.
我建议玩它,并调整套接字上的超时行为.
因为,你想要的是一段时间后停止收听(间隔获取).
所以,云试图将超时与阻塞结合起来,一段时间后停止从流中读取数据:
$timeout = 60; // seconds
stream_set_blocking($socket, true);
stream_set_timeout($socket, $timeout);
当你有一个流,1分钟后关闭,
您需要一个循环(具有固定的退出条件)来触发下一个请求.
class SoapClientTimeout extends SoapClient
{
public function __construct ($wsdl, $options = null)
{
if (!$options) $options = [];
$this->_connectionTimeout = @$options['connection_timeout'] ?: ini_get ('default_socket_timeout');
$this->_socketTimeout = @$options['socket_timeout'] ?: ini_get ('default_socket_timeout');
unset ($options['socket_timeout']);
parent::__construct($wsdl, $options);
}
/**
* Override parent __doRequest and add "timeout" functionality.
*/
public function __doRequest ($request, $location, $action, $version, $one_way = 0)
{
// fetch host, port, and scheme from url.
$url_parts = parse_url($location);
$host = $url_parts['host'];
$port = @$url_parts['port'] ?: ($url_parts['scheme'] == 'https' ? 443 : 80);
$length = strlen ($request);
// create HTTP SOAP request.
$http_req = "POST $location HTTP/1.0\r\n";
$http_req .= "Host: $host\r\n";
$http_req .= "SoapAction: $action\r\n";
$http_req .= "Content-Type: text/xml; charset=utf-8\r\n";
$http_req .= "Content-Length: $length\r\n";
$http_req .= "\r\n";
$http_req .= $request;
// switch to SSL, when requested
if ($url_parts['scheme'] == 'https') $host = 'ssl://'.$host;
// connect
$socket = @fsockopen($host, $port, $errno, $errstr, $this->_connectionTimeout);
if (!$socket) {
throw new SoapFault('Client',"Failed to connect to SOAP server ($location): $errstr");
}
// send request with socket timeout
stream_set_timeout($socket, $this->_socketTimeout);
fwrite ($socket, $http_req);
// start reading the response.
$http_response = stream_get_contents($socket);
// close the socket and throw an exception if we timed out.
$info = stream_get_meta_data($socket);
fclose ($socket);
if ($info['timed_out']) {
throw new SoapFault ('Client', "HTTP timeout contacting $location");
}
// the stream contains XML data
// lets extract the XML from the HTTP response and return it.
$response = preg_replace (
'/
\A # Start of string
.*? # Match any number of characters (as few as possible)
^ # Start of line
\r # Carriage Return
$ # End of line
/smx',
'', $http_response
);
return $response;
}
}