[英]SoapFault exception: Could not connect to host
有时无法调用 Web 服务。
这个问题一直在发生。
可能是什么问题呢?
Error:
SoapFault exception: [HTTP] Could not connect to host in
0 [internal function]: SoapClient->__doRequest('<?xml version="...', http://.', '', 1, 0)
问题解决了 是缓存的问题
ini_set('soap.wsdl_cache_enabled',0);
ini_set('soap.wsdl_cache_ttl',0);
为了完整性,我添加了我的评论,因为此处列出的解决方案对我没有帮助。 在 PHP 5.6 上,SoapClient 第一次调用SoapClient::SoapClient
指定的 WSDL URL,在连接到它并接收结果后,它尝试连接到结果中指定的 WSDL:
<soap:address location="http://"/>
如果 WSDL 与您在SoapClient::SoapClient
指定的不同并且无法访问(我的情况是使用http://host.local/ 的SoapUI),则调用失败并显示错误Could not connect to host
。
PHP 5.4 中的行为有所不同,它始终使用SoapClient::SoapClient
的 WSDL。
主机已关闭或响应非常慢。 如果响应缓慢,您可以尝试通过connection_timeout
选项或通过default_socket_timeout
设置增加超时,看看是否可以减少失败。
http://www.php.net/manual/en/soapclient.soapclient.php
http://www.php.net/manual/en/filesystem.configuration.php#ini.default-socket-timeout
您还可以像 zanlok 指出的那样包含错误处理以重试几次。 如果您确实有用户在等待这些 SOAP 调用,那么您需要将它们排队并在后台处理它们,并在它们完成时通知用户。
错误配置的服务将默认命名空间保留在 tempuri.org
这意味着与 wsdl 的连接将工作,但函数调用将失败。
堆栈跟踪:
SoapClient->__doRequest('http://example.com...', ' http://tempuri.org ....', 2, 0)
要修复此问题,您必须使用__setLocation()
显式设置位置
$this->soapClient = new \SoapClient(WS_URL);
$this->soapClient->__setLocation(WS_URL);
php.ini 文件中有一个soap 配置部分,它控制wsdl 访问缓存,可能显示为:
[soap]
; Enables or disables WSDL caching feature.
soap.wsdl_cache_enabled=1 ;
Sets the directory name where SOAP extension will put cache files.
soap.wsdl_cache_dir="/tmp"
; (time to live) Sets the number of second while cached file will be used ; instead of original one.
soap.wsdl_cache_ttl=86400
如果启用了 wsdl 文件缓存,则在 php 代码中更改 wsdl URI 时可能会导致此问题。 在本例中,您可以删除/tmp
目录下以wsdl-
开头的文件。 或者你只是设置soap.wsdl_cache_enabled=0;
和soap.wsdl_cache_ttl=0;
每次访问该页面时,PHP 都会获取 wsdl 文件。
这对我有用
$opts = array(
'ssl' => array('verify_peer' => false, 'verify_peer_name' => false)
);
if (!isset($this->soap_client)) {
$this->soap_client = new SoapClient($this->WSDL, array(
'soap_version' => $this->soap_version,
'location' => $this->URL,
'trace' => 1,
'exceptions' => 0,
'stream_context' => stream_context_create($opts)
));
在我们的例子中,这是一个密码协商问题。 我们随机收到此错误。 我们通过强制这样的密码解决了我们的问题:
$soapClient = new SoapClient ('http://example.com/soap.asmx?wsdl',
array (
"stream_context" => stream_context_create (
array (
'ssl' => array (
'ciphers'=>'AES256-SHA'
)
)
)
)
);
看起来 PHP 并没有在每次服务调用时协商相同的密码。
我自己遇到了这个问题,经过多次挖掘,我最终发现了 ubuntu 的这个错误:
https://bugs.launchpad.net/ubuntu/+source/openssl/+bug/965371
具体来说
https://bugs.launchpad.net/ubuntu/+source/openssl/+bug/965371/comments/62
openssl s_client -connect site.tld:443
失败了,但是openssl s_client -tls1 -connect site.tld:443
成功了。 在我的特殊情况下,输出的一部分包括New, TLSv1/SSLv3, Cipher is RC4-MD5
所以我适当地设置了 php 上下文 ssl/cipher 值。
在我的情况下,它在连接到 wsdl 后工作,使用函数__setLocation()
再次定义位置,因为调用失败并出现错误:
无法连接到主机
如果 WSDL 与SoapClient::SoapClient
指定的不同,就会发生这种情况。
似乎错误SoapFault exception: Could not connect to host
可能是由几种不同的原因引起的。 在我的情况下,它不是由代理、防火墙或 DNS 引起的(我实际上有来自同一台机器的 SOAP 连接,使用nusoap工作,没有任何特殊设置)。
最后我发现它是由我在 SoapClient 构造local_cert
选项中引用的无效pem
文件引起的。
解决方案:当我从pem
文件中删除证书链时,它只包含证书和私钥,SOAP 调用开始通过。
在我的情况下,wsdl 中的服务地址是错误的。
我的 wsdl 网址是。
https://myweb.com:4460/xxx_webservices/services/ABC.ABC?wsdl
但是那个xml结果中的服务地址是。
<soap:address location="http://myweb.com:8080/xxx_webservices/services/ABC.ABC/"/>
我只是将该 xml 保存到本地文件并将服务地址更改为。
<soap:address location="https://myweb.com:4460/xxx_webservices/services/ABC.ABC/"/>
祝你好运。
终于找到原因了,是因为库在你的系统上找不到CA包。 PHP >= v5.6 默认自动设置verify_peer为 true。 但是,并非所有系统在磁盘上都有已知的 CA 包。
您可以尝试以下程序之一:
1.如果您的系统上有CA文件,请将php.ini
中的openssl.cafile
或curl.cainfo
设置为您的CA文件的路径。
2.手动指定你的SSL CA文件位置
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($cHandler, CURLOPT_CAINFO, $path-of-your-ca-file);
3.禁用verify_peer
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
对于那些与我一样在使用 laravel artisan 控制台命令而苦苦挣扎的人,该命令向外部肥皂服务器的相同 wsdl 发出大量请求,然后在一段时间后因Could not connect to host
错误而失败。
问题是因为我每次在发出请求之前都在创建新的SoapClient
实例。 不要那样做。 创建一次并从同一客户端发出每个请求。
希望能帮助到你。
对我来说,这是一个证书问题。 以下为我工作
$context = stream_context_create([
'ssl' => [
// set some SSL/TLS specific options
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
]
]);
$client = new SoapClient(null, [
'location' => 'https://...',
'uri' => '...',
'stream_context' => $context
]);
如果您的服务器上有防火墙,请确保打开 SOAP 使用的端口。
就我而言,我必须打开端口 1664。
iptables -t filter -A INPUT -p tcp --dport 1664 -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport 1664 -j ACCEPT
如果 ujava 的解决方案不能帮助你,你可以尝试使用 try/catch 来捕捉这个致命的,这对我来说很好。
try{
$res = $client->__call('LineStopQueryJson',array('Parameters' => $params));
}catch(SoapFault $e){
print_r($client);
}
对我来说,WCF 服务的 app.config 中的基地址中存在这个问题:当我使用时:
<baseAddresses><add baseAddress="http://127.0.0.1:9022/Service/GatewayService"/> </baseAddresses>
如果使用 .net 连接公共 ip 或域就可以了。
但是当使用 PHP 的 SoapClient 连接到“ http://[online ip]:9022/Service/GatewayService
”时,会抛出异常“Coulod not connect to host”
我已将 baseAddress 更改为 [online ip]:9022,一切正常。
对我来说,这是一个 DNS 问题。 我的 VPS 的域名服务器坏了,所以我通过编辑我的 /etc/resolv.conf 切换到 Google 的: nameserver 8.8.8.8 nameserver 8.8.4.4
此错误的另一个可能原因是当您创建并保持打开的连接过多时。
SoapClient 默认发送 HTTP 标头Connection: Keep-Alive
(通过构造函数选项keep_alive
)。 但是,如果您为队列中的每个调用创建一个新的 SoapClient 实例,则每次都会创建并保持打开一个新连接。 如果调用执行得足够快,您最终将遇到 1000 个左右的打开连接的限制,这会导致SoapFault: Could not connect to host
。
因此,请确保您创建了 SoapClient 一次,并将其重用于后续调用。
我有一个糟糕的 php.ini 配置。 验证路径和证书有效性...
[openssl]
openssl.cafile = "C:/good/phpath/ca-bundle.crt"
因为我的新 \\SoapClient($wsdl) 是 https !
只是为了帮助遇到此错误的其他人, <soap:address location="https://some.url"/>
的 url 具有无效证书并导致错误。
对我来说,这是httpd
服务(Fedora 24)中的一个问题。 一个简单的重启就成功了:
sudo service httpd restart
如果连接是通过 SSL,则可能是服务器而不是客户端的问题(这是我的情况)。
在 PHP 5.6 和 7 以上的版本中,检查服务器证书中使用的 CipherSuite 很重要。 有此版本允许的密码的完整列表以及此 Web 链接中没有的密码的完整列表: https : //wiki.mozilla.org/Security/Server_Side_TLS#Recommended_Ciphersuite
如果使用的密码不被允许(它是一个不推荐使用的算法),SoapClient 会收到“无法连接到主机”并且没有更多关于它的跟踪。
例如,使用的密码可以由 SoapUI 等客户端在“SSL 信息”部分进行检查。
互联网上没有线程论坛对此进行处理。
在我的情况下,主机需要 TLS 1.2,因此需要使用 crypto_method ssl 参数来强制执行。
$client = new SoapClient($wsdl,
array(
'location' => $location,
'keep_alive' => false,
"stream_context" => stream_context_create([
'ssl' => [
'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT,
]
]),
'trace' => 1, // used for debug
)
);
就我而言,禁用 SELINUX 允许 PHP 调用我的 WebService。 我使用 Apache2 在 FPM 中运行 PHP
SELinux 状态:
# sestatus
禁用 SELinux :
启用 SELinux :
# setenforce 1
永久禁用:
edit this file /etc/selinux/config
版本检查帮助了我 OpenSSL。 OpenSSL_1_0_1f 不支持 TSLv.1_2 ! 在github openssl/openssl上检查版本和与 TSLv.1_2 的兼容性。 并使用新的 openssl 重新生成您的证书
openssl pkcs12 -in path.p12 -out newfile.pem
PS我不知道它们是什么,但是这个解决方案真的很有帮助。
这很可能是指连接问题。 可能是您的 Internet 连接已关闭,或者您尝试使用的 Web 服务已关闭。 我建议使用此服务来查看网络服务是否在线: http : //downforeveryoneorjustme.com/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.