【问题标题】:PHP SOAP keeps returning old resultsPHP SOAP 不断返回旧结果
【发布时间】:2016-08-03 08:16:38
【问题描述】:

我在尝试使用 PHP 使用 SOAP 服务时遇到了一个奇怪的问题。它忽略了我的请求,并不断返回最后一个命令的结果! SOAP 驻留在收银机中,它有一个指向公共 IP 端点的“错误”wsdl,我不得不手动编辑它。 WSDL 文件位于我下载的http://192.168.1.20/MyEcrResponce.wsdl 中,并将所有错误的 IP 引用替换为“192.168.1.20”,然后我将其保存为本地 MyEcrResponce.wsdl:

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://192.168.1.20/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://192.168.1.20/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <wsdl:types>
    <s:schema elementFormDefault="qualified" targetNamespace="http://192.168.1.20/">
      <s:element name="Cmd">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="1" maxOccurs="1" name="CmdText"   type="s:string" />
          </s:sequence>
        </s:complexType>
      </s:element>
      <s:element name="CmdResponse">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="1" maxOccurs="1" name="CmdReply"  type="s:string" />
            <s:element minOccurs="1" maxOccurs="1" name="LcdLine1"  type="s:string" />
            <s:element minOccurs="1" maxOccurs="1" name="LcdLine2"  type="s:string" />
          </s:sequence>
        </s:complexType>
      </s:element>
      <s:element name="GetAppStatus">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="1" maxOccurs="1" name="SerialNo"    type="s:string" />
            <s:element minOccurs="1" maxOccurs="1" name="RetData"     type="s:string" />
          </s:sequence>
        </s:complexType>
      </s:element>
      <s:element name="GetAppStatusResponse">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="1" maxOccurs="1" name="GetAppStatusResult" type="s:unsignedByte" />
            <s:element minOccurs="1" maxOccurs="1" name="RetData"   type="s:string" />
          </s:sequence>
        </s:complexType>
      </s:element>    
    </s:schema>
  </wsdl:types>
  <wsdl:message name="CmdSoapIn">
    <wsdl:part name="parameters" element="tns:Cmd" />
  </wsdl:message>
  <wsdl:message name="CmdSoapOut">
    <wsdl:part name="parameters" element="tns:CmdResponse" />
  </wsdl:message>
  <wsdl:message name="GetAppStatusSoapIn">
    <wsdl:part name="parameters" element="tns:GetAppStatus" />
  </wsdl:message>
  <wsdl:message name="GetAppStatusSoapOut">
    <wsdl:part name="parameters" element="tns:GetAppStatusResponse" />
  </wsdl:message>
  <wsdl:portType name="MyEcrResponceSoap">
    <wsdl:operation name="Cmd">
      <wsdl:input message="tns:CmdSoapIn" />
      <wsdl:output message="tns:CmdSoapOut" />
    </wsdl:operation>
    <wsdl:operation name="GetAppStatus">
      <wsdl:input message="tns:GetAppStatusSoapIn" />
      <wsdl:output message="tns:GetAppStatusSoapOut" />
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="MyEcrResponceSoap" type="tns:MyEcrResponceSoap">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="Cmd">
      <soap:operation soapAction="http://192.168.1.20/Cmd" style="document" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="GetAppStatus">
      <soap:operation soapAction="http://192.168.1.20/GetAppStatus" style="document" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>    
  </wsdl:binding>
  <wsdl:service name="MyEcrResponce">
    <wsdl:port name="MyEcrResponceSoap" binding="tns:MyEcrResponceSoap">
      <soap:address location="http://192.168.1.20/MyEcrResponce/" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

我在 C# 中使用表单创建了一个客户端,将解决方案中的所有引用从公共 IP 替换为 192.168.1.20,并且工作正常:

private void button1_Click(object sender, EventArgs e)
{
    string reply = "";
    string LcdMsg1 = "";
    string LcdMsg2 = "";

    Uri ur = new Uri("http://192.168.1.20/MyEcrResponce.cgx");

    DeviceWS.MyEcrResponceSoapClient DevHD = new DeviceWS.MyEcrResponceSoapClient();
    DevHD.Endpoint.Address = new System.ServiceModel.EndpointAddress(ur);

    DevHD.ClientCredentials.UserName.UserName = "user";
    DevHD.ClientCredentials.UserName.Password = "pass";     

    reply = DevHD.Cmd(CmdTxt.Text, out LcdMsg1, out LcdMsg2);

    ReplyTxt.Text = reply;
    LCD01.Text = LcdMsg1;
    LCD02.Text = LcdMsg2;    
}

我的 PHP 客户端如下所示:

$client = new SoapClient(
dirname(__FILE__) . DIRECTORY_SEPARATOR . 'MyEcrResponce.wsdl', 
array('location' => 'http://192.168.1.20/MyEcrResponce.cgx', 
    'login' => 'user', 
    'password' => 'pass', 
    'trace' => 0, 
    'cache_wsdl' => WSDL_CACHE_NONE));  

$cmd = new StdClass();
$cmd->CmdText = 'a/'; 

var_dump($client->Cmd($cmd));

无论我尝试哪种组合,在 PHP 中我总是得到 C# 客户端命令的最后一个结果。似乎所有使用 PHP 的请求都被忽略了。似乎有一个 C# 可以超越的缓存,但 PHP 不能。在 php.ini 中,'soap.wsdl_cache_enabled' 和 'soap.wsdl_cache' 都设置为 0。SoapUI 和其他 SOAP 测试仪的行为相同(错误)。有什么想法吗?

更新 1: PHP $client->__getTypes();返回:

array (4) [
    string (31) "struct Cmd {
 string CmdText;
}"
    string (76) "struct CmdResponse {
 string CmdReply;
 string LcdLine1;
 string LcdLine2;
}"
    string (58) "struct GetAppStatus {
 string SerialNo;
 string RetData;
}"
    string (82) "struct GetAppStatusResponse {
 unsignedByte GetAppStatusResult;
 string RetData;
}"
]

更新 2: 使用 this post 我在 C# 客户端中启用了跟踪日志来检查正在工作的 SOAP 请求,这是一个:

{
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://192.168.1.20/Cmd"
Accept-Encoding: gzip, deflate,gzip, deflate
Authorization: Basic xxxxxxxxxxxxxxxx
Host: 192.168.1.20
Content-Length: 207
Expect: 100-continue
}

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Body>
        <Cmd xmlns="http://192.168.1.20/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <CmdText>a/</CmdText>
        </Cmd>
    </s:Body>
</s:Envelope>

不幸的是,当我将请求复制粘贴到 PHP 或 SoapUI 时,结果仍然相同。

更新 3: 所以,今天是星期一。周五收银机和 PHP 服务器都关闭了,我今天打开了它们。在我运行 PHP 脚本之前,我从 PHP 服务器中清除了所有缓存文件,并且我收到了周五发送的最后一个成功命令的回复!!!我快要相信我必须非常愚蠢......

【问题讨论】:

  • 试试 put ini_set('soap.wsdl_cache_enabled', '0'); ini_set('soap.wsdl_cache_ttl', '0');
  • 我已经提到缓存被禁用了。

标签: c# php web-services soap websocket


【解决方案1】:

至少在某种程度上,我设法解决了我的问题。我无法使 SOAP 请求正常工作,但我设法使用 websockets 成功通信。我坚持使用 SOAP,因为我有更多的经验,但我不得不放弃。我想要一些非常轻量级的东西(我想避免使用基于作曲家的大型库),所以经过大量搜索后,我找到了 this post,这是我根据自己的需要量身定制的,现在我得到了宝贵的回复。对于面临相同或类似问题的任何其他人,收银机正在使用 RBS 软件(希腊公司)和 Keil-EWeb 服务器。我修改后的工作 PHP 代码如下:

class WebsocketClient
{
    private $_Socket = null;

    public function __construct($host, $port)
    {
        $header = "GET / HTTP/1.1\r\n";
        $header.= "Host: ".$host.":".$port."\r\n";

        $this->_Socket = fsockopen($host, $port, $errno, $errstr, 2); 
        fwrite($this->_Socket, $header) or die('Error: ' . $errno . ':' . $errstr); 
        $response = fread($this->_Socket, 2000);
    }

    public function __destruct()
    {
        fclose($this->_Socket);
    }

    public function sendData($data)
    {
        fwrite($this->_Socket, $data ) or die('Error:' . $errno . ':' . $errstr); 
        $wsData = fread($this->_Socket, 2000);
        $retData = trim($wsData,"\x00\xff");        
        return mb_convert_encoding($retData,'utf-8','ISO-8859-7'); // Returns garbage in case of greek (or other letters)
    }
}

$WebSocketClient = new WebsocketClient('192.168.1.20', 9101);
echo $WebSocketClient->sendData('a/');
unset($WebSocketClient);

【讨论】:

    【解决方案2】:

    试试看

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

    在创建客户端之前。

    我现在在创建客户端时使用 NO_CACHE 有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-24
      • 1970-01-01
      • 1970-01-01
      • 2011-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多