【问题标题】:SoapFault exception: Could not connect to hostSoapFault 异常:无法连接到主机
【发布时间】:2010-11-30 21:29:22
【问题描述】:

有时调用网络服务失败。

这个问题一直在发生。

可能是什么问题?

Error:
    SoapFault exception: [HTTP] Could not connect to host in 
    0 [internal function]: SoapClient->__doRequest('<?xml version="...', http://.', '', 1, 0)

【问题讨论】:

  • 可能是网络连接问题,尤其是服务不可用。尝试在您的应用程序中构建容错功能 - 或许自动重试最多 3 次?
  • 另一个原因可能是 SSL 证书验证失败(例如自签名证书)。可以允许自签名证书,请参阅stackoverflow.com/a/39242417/1119601
  • 是的,我遇到了同样的问题,我设法通过在本地禁用 ssl 来工作:'stream_context'=&gt; stream_context_create(array('ssl'=&gt; array('verify_peer'=&gt;false,'verify_peer_name'=&gt;false)))

标签: php soap


【解决方案1】:

问题解决了。问题是缓存

ini_set('soap.wsdl_cache_enabled',0);
ini_set('soap.wsdl_cache_ttl',0);

【讨论】:

  • 似乎“无法连接到主机”与缓存无关。
  • 大概是这样的: $client = new SoapClient($url, array('cache_wsdl' => WSDL_CACHE_NONE));
  • 常见,在我国我们称之为“用洗澡水泼婴儿”。缓存可能存在问题,但是在 SOAP wsdl 的情况下禁用缓存是一个沉重的步骤。这意味着每次使用 PHP 类时都要检索和解析一个大的 XML 文件。不敢相信这是票数最高的答案...
  • 此错误消息过于笼统:bugs.php.net/bug.php?id=68782 错误可能来自超时、代理、缓存交互bugs.php.net/bug.php?id=69783 请查看下面的答案,但请不要对此进行投票。
  • Bug 69783 会在配置代理时导致 WSDL 缓存失败。在修复此错误之前,需要禁用 WSDL 缓存。
【解决方案2】:

为了完整起见,我添加了我的评论,因为此处列出的解决方案对我没有帮助。在 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。

【讨论】:

  • 虽然我的错误消息是相同的(无法连接到主机),但只需降级到以前版本的 php (5.6 > 5.3) 就可以让脚本像以前一样运行。
  • 您可以使用SoapClient::__setLocation()`调整此行为。
  • user3584460 和 @geomagas 谢谢你们,你们救了我,我为此快疯了
  • 也是我的情况。更有趣的是,WSDL 中返回的“位置”URL 会根据负载均衡器将我的请求转发到哪个服务器而发生变化——有时可以,有时不行。强制定位到正确的 URL 为我解决了这个问题。
【解决方案3】:

主机已关闭或响应非常缓慢。如果响应缓慢,您可以尝试通过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 调用,那么您需要将它们排队并在后台处理它们,并在它们完成时通知用户。

【讨论】:

  • 我发现如果在我的SoapClient 选项中没有设置connection_timeout (>= 1),我会遇到could not connect to host。设置此选项后,问题就解决了。
  • @GregK 这很奇怪。如果没有明确设置,我认为 connect_timeout 应该默认为 default_socket_timeout 值(默认为 60 秒)。
  • 是的,我是这么认为的,但我设置了default_socket_timeout,但它没有任何效果。 PHP 中有一个长期存在的错误,其中default_socket_timeout 也不适用于 SSL 连接(无论如何对于 SoapClient)。
  • @GregK 你能提供这个长期存在的错误的链接吗?
  • @marcovtwout 6 年后?!看起来它是在我在 PHP 5.5.18 中发表评论几天后修补的:bugs.php.net/bug.php?id=41631
【解决方案4】:

misconfigured 服务使用 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);

【讨论】:

  • 这使用__soapCall方法解决了我的问题,谢谢。
  • 在寻找解决方案数小时后,它救了我。 __setLocation 是我的解决方案。谢谢
【解决方案5】:

这对我有用

$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)
  ));

【讨论】:

  • 我也有同样的问题。所以你的 $this->WSDL 和 $this->URL 指向同一个 url?
【解决方案6】:

在你的 php.ini 文件中有一个soap config部分,它控制着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 文件。

【讨论】:

    【解决方案7】:

    在我们的例子中,这是一个密码协商问题。我们随机收到此错误。我们通过强制使用这样的密码解决了我们的问题:

    $soapClient = new SoapClient ('http://example.com/soap.asmx?wsdl',
        array (
            "stream_context" => stream_context_create (
                array (
                    'ssl' => array (
                        'ciphers'=>'AES256-SHA'
                    )
                )
            )
        )
    );
    

    看起来 PHP 没有在每次服务调用时协商相同的密码。

    【讨论】:

    • 从 PHP 7.2 升级到 7.3 后,我们在调用 WorldPay/Envoy 时遇到了 Soap 错误。在我们的SoapClient 选项中设置此密码解决了我们的问题。
    • 你怎么知道的?暴力配置?您在任何源链接参考中看到了吗?
    【解决方案8】:

    我自己遇到了这个问题,经过大量挖掘,我最终发现了 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 值。

    【讨论】:

      【解决方案9】:

      在我的情况下,它在连接到 wsdl 后工作,使用函数 __setLocation() 再次定义位置,因为调用失败并出现错误:

      无法连接到主机

      如果 WSDL 与 SoapClient::SoapClient 中指定的不同,就会发生这种情况。

      【讨论】:

        【解决方案10】:

        似乎错误SoapFault exception: Could not connect to host 可能是由几个不同的原因引起的。在我的情况下,它不是由代理、防火墙或 DNS 引起的(实际上我有一个来自同一台机器的 SOAP 连接,使用 nusoap 工作,没有任何特殊设置)。

        最后我发现它是由我在 SoapClient 构造函数的local_cert 选项中引用的无效pem 文件引起的。

        解决方案: 当我从 pem 文件中删除证书链时,它包含证书和私钥,SOAP 调用开始进行。

        【讨论】:

        • 这在我的情况下有效。这很有趣,因为旧证书已与链条一起使用。 (这是证书更新)。谢谢雅各布。
        • @Jacob 您用来生成 PEM 文件的命令是什么?
        • 我不记得具体是如何生成pem 文件的,但我记得我只是打开了一个普通的文本编辑器并删除了引用证书链的部分,而其他部分保持不变。
        【解决方案11】:

        在我的情况下,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/"/>
        

        祝你好运。

        【讨论】:

          【解决方案12】:

          我终于找到了原因,因为库在你的系统上找不到 CA 包。 PHP >= v5.6 默认自动将 verify_peer 设置为 true。但是,并非所有系统在磁盘上都有已知的 CA 捆绑包。

          您可以尝试以下方法之一:

          1.如果您的系统上有 CA 文件,请将 php.ini 中的 openssl.cafilecurl.cainfo 设置为 CA 文件的路径。

          2.手动指定您的 SSL CA 文件位置

          curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);  
          curl_setopt($cHandler, CURLOPT_CAINFO, $path-of-your-ca-file);
          

          3.disabled verify_peer

          curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
          

          【讨论】:

            【解决方案13】:

            对于那些与我一样挣扎于 laravel artisan 控制台命令的人,该命令向外部肥皂服务器的相同 wsdl 发出大量请求,然后在一段时间后因Could not connect to host 错误而失败。

            问题是因为我每次在发出请求之前都在创建新的SoapClient 实例。不要那样做。创建一次并从同一个客户端发出每个请求。

            希望对你有帮助。

            【讨论】:

              【解决方案14】:

              对我来说,这是一个证书问题。以下为我工作

              $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
              ]);
              

              【讨论】:

              • 别忘了:数组必须用array( key =&gt; val )语法prior to PHP version 5.4定义。我将其复制/粘贴到 PHP 5.2 应用程序中,并遇到语法错误,直到更改为旧数组语法。
              【解决方案15】:

              对我来说,这是一个 DNS 问题。我的 VPS 的名称服务器崩溃了,所以我通过将 /etc/resolv.conf 编辑为: 名称服务器 8.8.8.8 域名服务器 8.8.4.4

              【讨论】:

                【解决方案16】:

                如果您的服务器上有防火墙,请确保打开 SOAP 使用的端口。

                就我而言,我必须打开端口 1664。

                iptables -t filter -A INPUT -p tcp --dport 1664 -j ACCEPT
                iptables -t filter -A OUTPUT -p tcp --dport 1664 -j ACCEPT
                

                【讨论】:

                • 对我来说问题也出在端口上。 SOAP 服务器使用了为连接禁用的端口。
                • 如何找出 SOAP 尝试使用的端口?
                • @ujava 得到它在找到这个线程后解决了完全相同的错误,搜索$rcmail_config['soap_url'] = 配置不正确,更正服务器+端口+https(在我的情况下)做到了
                【解决方案17】:

                如果 ujava 的解决方案不能帮助你,你可以尝试使用 try/catch 来捕捉这个致命的,这对我来说很好。

                try{
                    $res = $client->__call('LineStopQueryJson',array('Parameters' => $params));
                }catch(SoapFault $e){
                    print_r($client);
                }
                

                【讨论】:

                  【解决方案18】:

                  对我来说,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,一切正常。

                  【讨论】:

                    【解决方案19】:

                    此错误的另一个可能原因是您创建并保持打开的连接过多。

                    SoapClient 默认发送 HTTP Header Connection: Keep-Alive(通过构造函数选项keep_alive)。但是,如果您为队列中的每个调用创建一个新的 SoapClient 实例,这将每次都创建并保持打开一个新连接。如果调用执行得足够快,您最终将遇到 1000 个左右打开连接的限制,这将导致 SoapFault: Could not connect to host

                    因此,请确保您创建一次 SoapClient 并将其重用于后续调用。

                    【讨论】:

                      【解决方案20】:

                      我的 php.ini 配置错误。验证路径和证书的有效性...

                      [openssl]
                      openssl.cafile = "C:/good/phpath/ca-bundle.crt"
                      

                      因为我的新 \SoapClient($wsdl) 是 https !

                      【讨论】:

                        【解决方案21】:

                        为了帮助遇到此错误的其他人,&lt;soap:address location="https://some.url"/&gt; 中的 url 的证书无效并导致错误。

                        【讨论】:

                          【解决方案22】:

                          对我来说,这是httpd 服务(Fedora 24)中的一个问题。一个简单的重启就可以了:

                          sudo service httpd restart
                          

                          【讨论】:

                            【解决方案23】:

                            如果连接是通过 SSL,可能是服务器而不是客户端的问题(这是我的情况)。

                            在高于 5.6 和 7 的 PHP 版本中,检查服务器证书中使用的 CipherSuite 很重要。 此版本允许的密码的完整列表和此 Web 链接中不允许的密码的完整列表:https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_Ciphersuite

                            如果使用的密码不被允许(这是一个不推荐使用的算法),SoapClient 会收到“无法连接到主机”并且没有更多关于它的跟踪。

                            例如,SoapUI 等客户端可以在“SSL 信息”部分检查所使用的密码。

                            互联网上没有讨论这个的主题论坛。

                            也检查一下:http://php.net/manual/en/migration56.openssl.php

                            【讨论】:

                              【解决方案24】:

                              在我的情况下,主机需要 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
                                      )
                                  );
                              

                              【讨论】:

                                【解决方案25】:

                                在我的例子中,禁用的 SELINUX 允许 PHP 调用我的 WebService。 我用 Apache2 在 FPM 中运行 PHP

                                SELinux 状态:

                                # sestatus
                                

                                禁用 SELinux:

                                setenforce 0

                                启用 SELinux:

                                # setenforce 1
                                

                                永久禁用:

                                edit this file /etc/selinux/config
                                

                                【讨论】:

                                  【解决方案26】:

                                  版本检查帮助了我的 OpenSSL。 OpenSSL_1_0_1f 不支持 TSLv.1_2 ! 在github openssl/openssl 上检查版本和与 TSLv.1_2 的兼容性 .并使用新的 openssl 重新生成您的证书

                                  openssl pkcs12 -in path.p12 -out newfile.pem
                                  

                                  P.S 我不知道它们有什么缺点,但这个解决方案真的很有帮助。

                                  【讨论】:

                                    【解决方案27】:

                                    这很可能是指连接问题。可能是您的 Internet 连接已关闭,或者您尝试使用的 Web 服务已关闭。我建议使用这个服务来查看网络服务是否在线:http://downforeveryoneorjustme.com/

                                    【讨论】:

                                    • 如果我的互联网连接中断,我如何在网上发布任何内容,如何从远程服务器获得响应到我的本地 wamp 或 SOAPUI 工具。
                                    猜你喜欢
                                    • 2017-04-14
                                    • 2021-11-22
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 2019-04-08
                                    • 2016-08-20
                                    • 1970-01-01
                                    • 1970-01-01
                                    相关资源
                                    最近更新 更多