为什么我在使用SOAP UI和Java客户端访问Web服务时收到java.net.SocketException: Connection reset错误?

13

我正在将一个Visual FoxPro应用程序转换为Java web应用程序,应用程序的一个小但重要的部分向web服务发出SOAP请求。

我编写了3个测试客户端来调用该Web服务,我还通过SOAP UI进行了测试。我测试这个Web服务的每一个测试都返回错误:java.net.SocketException:连接重置。所以显然我在每种测试方法中都漏掉了同一件事情,或者做错了同一件事情。

我有Foxpro代码,并且已成功提交了请求并接收到有效响应。但是我没有任何使用Foxpro的经验,因此我一直在努力理解Foxpro中有效的代码与我在Java中编写的新代码之间的差异。

我希望有更多关于Soap和Web服务经验的人可以查看我的代码,可能会尝试它们自己,并帮助我理解问题所在。

我将提供Web服务URL以及所有我的代码。我还将提供在Foxpro中工作的命令行代码。

Foxpro代码使用CreateObject("Microsoft.XMLHTTP")。 我通过研究学到,这也在ASP、VB.net和C#中使用。

1)这是我需要调用的Web服务:

Host: https://rlisapi.myfwc.com/

Soap Endpoint: https://rlisapi.myfwc.com/wsReceipts.asmx

WSDL: https://rlisapi.myfwc.com/wsReceipts.asmx?WSDL

该Web服务不包含WS-Security。凭据在请求本身中。当然,我不能提供这些信息,但我认为它们不需要来帮助我解决连接重置问题。

2)我创建的第一个客户端使用SAAJ API。以下是我的代码:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import javax.xml.soap.MessageFactory;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;

import org.apache.log4j.Logger;

import com.mycompany.webapp.domain.transaction.BusinessEntityTransaction;
import com.mycompany.webapp.domain.transaction.ccars.PaymentCart;
import com.mycompany.webapp.domain.transaction.rlis.RlisTransaction;

public class RlisService {
    private static Logger logger = Logger.getLogger("com.companyxyz.webapp.service.transaction.RlisService");   

    public List<BusinessEntityTransaction> getCurrentTransactions(PaymentCart paymentCart) {
        List<BusinessEntityTransaction> transactionList = new ArrayList<BusinessEntityTransaction>();
        List<RlisTransaction> rlisList = new ArrayList<RlisTransaction>();
        try {
            logger.info("Adding current transactions from RLIS system...");
            rlisList = this.getCurrentTransactionsViaSoapRequest();

            for (RlisTransaction tx : rlisList){
                //add transaction received from web service to transactionList
            }

        } catch (UnsupportedOperationException e) {
            e.printStackTrace();
        } catch (SOAPException e) {
            e.printStackTrace();
        }
        // do something with the rlisList - the list of RlisTransactions
        return transactionList;
    }

    private List<RlisTransaction> getCurrentTransactionsViaSoapRequest() 
            throws UnsupportedOperationException, SOAPException {
        List<RlisTransaction> rlisTransactions = new ArrayList<RlisTransaction>();
        // Create SOAP Connection
        try {
            SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
            SOAPConnection soapConnection = soapConnectionFactory.createConnection();

            // Send SOAP Message to SOAP Server
            String url = "https://rlisapi.myfwc.com/wsReceipts.asmx";
            SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url);

            // Process the SOAP Response

            printSOAPResponse(soapResponse);

            soapConnection.close();
        } catch (TransformerException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return rlisTransactions;
    }


    private static SOAPMessage createSOAPRequest() throws SOAPException, IOException {
        MessageFactory messageFactory = MessageFactory.newInstance();
        SOAPMessage soapMessage = messageFactory.createMessage();
        SOAPPart soapPart = soapMessage.getSOAPPart();

        //String serverURI = "http://rlisapi.outdoorlicensesolution.com/";

        // SOAP Envelope
        SOAPEnvelope envelope = soapPart.getEnvelope();
        //envelope.addNamespaceDeclaration("http://api.outdoorlicensesolution.com/RLIS/", serverURI);

        // SOAP Body
        SOAPBody soapBody = envelope.getBody();
        Name bodyName = envelope.createName("getDailyReceipts", "rlis", "http://api.outdoorlicensesolution.com/RLIS/");
        SOAPBodyElement getDailyReceiptsElement = soapBody.addBodyElement(bodyName); 

     //Name contentLenghName = envelope.createName("Content-Length");
        Name consumerPinName = envelope.createName("ConsumerPIN");
        Name agentIdName = envelope.createName("AgentID");
        Name receiptDateName = envelope.createName("ReceiptDate");

        //SOAPElement contentLengthElement = getDailyReceiptsElement.addChildElement(contentLenghName);        
        //contentLengthElement.addTextNode("494");

        SOAPElement consumerPinElement = getDailyReceiptsElement.addChildElement(consumerPinName);
        consumerPinElement.addTextNode("my-consumer-pin");

        SOAPElement agentIdElement = getDailyReceiptsElement.addChildElement(agentIdName);
        agentIdElement.addTextNode("000"); //not a real agent id

        SOAPElement receiptDateElement = getDailyReceiptsElement.addChildElement(receiptDateName);
        receiptDateElement.addTextNode("2013-07-01T00:00:00");



/*
//this is the soap request string from foxpro:
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Body>
<getDailyReceipts xmlns="http://api.outdoorlicensesolution.com/RLIS/">
<Content-Length>494</Content-Length>
<ConsumerPIN>APIKEY</ConsumerPIN>
<AgentID>AGENTID</AgentID>
<ReceiptDate>SALEDATE</ReceiptDate> 
</getDailyReceipts> 
</soap:Body> 
</soap:Envelope> 

 */
        soapMessage.saveChanges();

        /* Print the request message */
        System.out.print("Request SOAP Message = ");
        soapMessage.writeTo(System.out);
        System.out.println();

        return soapMessage; 
    }

    private static void printSOAPResponse(SOAPMessage soapResponse) throws TransformerException, SOAPException {
        logger.debug(soapResponse.getSOAPBody());
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        Source sourceContent = soapResponse.getSOAPPart().getContent();
        logger.debug("\nResponse SOAP Message = ");
        System.out.print("\nResponse SOAP Message = ");
        StreamResult result = new StreamResult(System.out);
        transformer.transform(sourceContent, result);

    }

}

(3) 我的客户端的下一个版本使用Socket和OutputStreamWriter。

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import javax.xml.soap.MessageFactory;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;

import org.apache.log4j.Logger;

import com.mycompany.webapp.domain.transaction.BusinessEntityTransaction;
import com.mycompany.webapp.domain.transaction.ccars.PaymentCart;
import com.mycompany.webapp.domain.transaction.rlis.RlisTransaction;

public class RlisService {
    private static Logger logger = Logger.getLogger("com.companyxyz.webapp.service.transaction.RlisService");   

    public List<BusinessEntityTransaction> getCurrentTransactions(PaymentCart paymentCart) {
        List<BusinessEntityTransaction> transactionList = new ArrayList<BusinessEntityTransaction>();
        List<RlisTransaction> rlisList = new ArrayList<RlisTransaction>();
        try {
            logger.info("Adding current transactions from RLIS system...");
            rlisList = this.getCurrentTransactionsViaXmlHttp();         
            for (RlisTransaction tx : rlisList){
                //add transaction received from web service to transactionList
            }

        } catch (UnsupportedOperationException e) {
            e.printStackTrace();
        }
        // do something with the rlisList 
        return transactionList;
    }

    private List<RlisTransaction> getCurrentTransactionsViaXmlHttp(){
        List<RlisTransaction> rlisTransactions = new ArrayList<RlisTransaction>();

        String xmldata = "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" +
        "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" +
        "xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\">" +
        "<soap:Body>" +
        "<getDailyReceipts xmlns=\"http://api.outdoorlicensesolution.com/RLIS/\">" +
        //"<Content-Length>494</Content-Length>" +
        "<ConsumerPIN>APIKEY</ConsumerPIN>" +
        "<AgentID>AGENTID</AgentID>" +
        "<ReceiptDate>SALEDATE</ReceiptDate>" +
        "</getDailyReceipts>" +
        "</soap:Body>" +
        "</soap:Envelope>";

        try{

          //Create socket
          String hostname = "rlisapi.myfwc.com";
          int port = 443;
          InetAddress  addr = InetAddress.getByName(hostname);
          Socket sock = new Socket(addr, port);
          //Socket sock = new Socket(hostname, port);

          //Send header
          String path = "https://rlisapi.myfwc.com/wsReceipts.asmx";
          BufferedWriter  wr = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream(),"UTF-8"));
          // You can use "UTF8" for compatibility with the Microsoft virtual machine.
          wr.write("POST " + path + " HTTP/1.0\r\n");
          wr.write("Host: rlisapi.myfwc.com\r\n");
          wr.write("Content-Length: " + xmldata.length() + "\r\n");
          wr.write("Content-Type: text/xml; charset=\"utf-8\"\r\n");
          wr.write("\r\n");

          //Send data
          wr.write(xmldata);
          wr.flush();

          // Response
          BufferedReader rd = new BufferedReader(new InputStreamReader(sock.getInputStream()));
          String line;
          while((line = rd.readLine()) != null)
          System.out.println(line);

        } catch (Exception e) {
              e.printStackTrace();
        }

        return rlisTransactions;
    }

}

(4) 我有一个类似的测试客户端,它使用 HttpUrlConnection

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

public class TestXmlClient {

    public static void main(String[] args) {
        String argUrl = "https://rlisapi.myfwc.com/wsReceipts.asmx";

        System.out.println("Test XML Client");

        String requestXml = 
                "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" +
                "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " +
                "xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\">" +
                "<soap:Body>" +
                "<getDailyReceipts xmlns=\"http://api.outdoorlicensesolution.com/RLIS/\">" +
                "<Content-Length>494</Content-Length>" +
                "<ConsumerPIN>my-consumer-pin</ConsumerPIN>" +
                "<AgentID>000</AgentID>" +  //not real agent id
                "<ReceiptDate>2013-07-01T00:00:00</ReceiptDate>" +
                "</getDailyReceipts>" +
                "</soap:Body>" +
                "</soap:Envelope>" ;

        System.out.println("Request: " + requestXml);

        //try {
        URL url;
        OutputStreamWriter writer = null;
        InputStreamReader reader = null;
        HttpURLConnection con = null;

        try {
            url = new URL (argUrl);
        con = (HttpURLConnection) url.openConnection();

        URLConnection urlc = url.openConnection();
        HttpURLConnection httpc = (HttpURLConnection)urlc;
        // only interested in the length of the resource
        httpc.setRequestMethod("HEAD");
        int len = httpc.getContentLength();

        System.out.println("length: " + len);

        // specify that we will send output and accept input
        con.setDoInput(true);
        con.setDoOutput(true);

        con.setConnectTimeout( 20000 );  // long timeout, but not infinite
        con.setReadTimeout( 20000 );

        con.setUseCaches (false);
        con.setDefaultUseCaches (false);

        // tell the web server what we are sending
        //con.setRequestProperty ( "Content-Type", "text/xml" );
        con.setRequestProperty ( "Content-Type", "text/xml; charset=utf-8" );
        //con.setRequestProperty("Connection", "close"); 

        writer = new OutputStreamWriter( con.getOutputStream() );

        writer.write(requestXml);
        writer.flush();
        writer.close();

        // reading the response
        reader = new InputStreamReader( con.getInputStream() );
        StringBuilder buf = new StringBuilder();
        char[] cbuf = new char[ 2048 ];
        int num;
        while ( -1 != (num=reader.read( cbuf ))) {
            buf.append( cbuf, 0, num );
        }
        String result = buf.toString();
        System.err.println( "\nResponse from server after POST:\n" + result );

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println(e.getStackTrace());
            e.printStackTrace();
        } catch (Exception e){
            e.printStackTrace();
        } finally{
            if (writer != null) { 
                try { 
                    writer.close(); 
                } catch (Exception e) { 
                    // ignore... 
                } 
            }
            if (reader != null) { 
                try { 
                    reader.close(); 
                } catch (Exception e) { 
                    // ignore... 
                } 
            } 

            if (con != null) { 
                try { 
                    con.disconnect(); 
                } catch (Exception e) { 
                    // ignore... 
                } 

            }   
        }
    }
}

最后,除了所有这些测试客户端之外,我还尝试使用SOAP UI提交各种请求。有趣的是,我无法从url加载wsdl,因此将wsdl源代码保存到本地文件中并使用它。

以下是Soap UI从wsdl文件生成的请求:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:rlis="http://api.outdoorlicensesolution.com/RLIS/">
   <soap:Header/>
   <soap:Body>
      <rlis:getDailyReceipts>
         <!--Optional:-->
         <rlis:ConsumerPIN>?</rlis:ConsumerPIN>
         <rlis:AgentID>?</rlis:AgentID>
         <rlis:ReceiptDate>?</rlis:ReceiptDate>
      </rlis:getDailyReceipts>
   </soap:Body>
</soap:Envelope>

本地保存了WSDL:

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://api.outdoorlicensesolution.com/RLIS/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" targetNamespace="http://api.outdoorlicensesolution.com/RLIS/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <wsdl:types>
    <s:schema elementFormDefault="qualified" targetNamespace="http://api.outdoorlicensesolution.com/RLIS/">
      <s:element name="getDailyReceipts">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" name="ConsumerPIN" type="s:string" />
            <s:element minOccurs="1" maxOccurs="1" name="AgentID" type="s:int" />
            <s:element minOccurs="1" maxOccurs="1" name="ReceiptDate" type="s:dateTime" />
          </s:sequence>
        </s:complexType>
      </s:element>
      <s:element name="getDailyReceiptsResponse">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" name="getDailyReceiptsResult" type="tns:ArrayOfReceipt" />
          </s:sequence>
        </s:complexType>
      </s:element>
      <s:complexType name="ArrayOfReceipt">
        <s:sequence>
          <s:element minOccurs="0" maxOccurs="unbounded" name="Receipt" nillable="true" type="tns:Receipt" />
        </s:sequence>
      </s:complexType>
      <s:complexType name="Receipt">
        <s:sequence>
          <s:element minOccurs="1" maxOccurs="1" name="OrderID" type="s:int" />
          <s:element minOccurs="1" maxOccurs="1" name="TotalSaleAmount" type="s:decimal" />
          <s:element minOccurs="1" maxOccurs="1" name="TaxCollectorFees" type="s:decimal" />
          <s:element minOccurs="1" maxOccurs="1" name="OrderDate" type="s:dateTime" />
          <s:element minOccurs="0" maxOccurs="1" name="OrderStatus" type="s:string" />
          <s:element minOccurs="1" maxOccurs="1" name="AmountToACH" type="s:decimal" />
          <s:element minOccurs="1" maxOccurs="1" name="CustomerID" type="s:int" />
          <s:element minOccurs="0" maxOccurs="1" name="CustomerName" type="s:string" />
          <s:element minOccurs="0" maxOccurs="1" name="ClerkUserName" type="s:string" />
          <s:element minOccurs="0" maxOccurs="1" name="TarponTagBegin" type="s:string" />
          <s:element minOccurs="0" maxOccurs="1" name="TarponTagEnd" type="s:string" />
          <s:element minOccurs="0" maxOccurs="1" name="ErrorMessage" type="s:string" />
        </s:sequence>
      </s:complexType>
    </s:schema>
  </wsdl:types>
  <wsdl:message name="getDailyReceiptsSoapIn">
    <wsdl:part name="parameters" element="tns:getDailyReceipts" />
  </wsdl:message>
  <wsdl:message name="getDailyReceiptsSoapOut">
    <wsdl:part name="parameters" element="tns:getDailyReceiptsResponse" />
  </wsdl:message>
  <wsdl:portType name="wsReceiptsSoap">
    <wsdl:operation name="getDailyReceipts">
      <wsdl:input message="tns:getDailyReceiptsSoapIn" />
      <wsdl:output message="tns:getDailyReceiptsSoapOut" />
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="wsReceiptsSoap" type="tns:wsReceiptsSoap">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="getDailyReceipts">
      <soap:operation soapAction="http://api.outdoorlicensesolution.com/RLIS/getDailyReceipts" style="document" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:binding name="wsReceiptsSoap12" type="tns:wsReceiptsSoap">
    <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="getDailyReceipts">
      <soap12:operation soapAction="http://api.outdoorlicensesolution.com/RLIS/getDailyReceipts" style="document" />
      <wsdl:input>
        <soap12:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap12:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="wsReceipts">
    <wsdl:port name="wsReceiptsSoap" binding="tns:wsReceiptsSoap">
      <soap:address location="https://rlisapi.myfwc.com/wsReceipts.asmx" />
    </wsdl:port>
    <wsdl:port name="wsReceiptsSoap12" binding="tns:wsReceiptsSoap12">
      <soap12:address location="https://rlisapi.myfwc.com/wsReceipts.asmx" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

我还会提供适用的Foxpro代码:

*******************************************
SALEDATE = DATE()-1
XMLRESPONSE = ''

M.AGENTID = '000'
M.APIKEY = 'my-consumer-pin'

M.cSALEDATE = STR(YEAR(SALEDATE),4) + '-' + PADL(ALLTRIM(STR(MONTH(SALEDATE),2)),2,'0') + '-' + PADL(ALLTRIM(STR(DAY(SALEDATE),2)),2,'0') + 'T00:00:00'

TEXT TO XMLHTTP NOSHOW
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Body>
<getDailyReceipts xmlns="http://api.outdoorlicensesolution.com/RLIS/">
<Content-Length>494</Content-Length>
<ConsumerPIN>APIKEY</ConsumerPIN>
<AgentID>AGENTID</AgentID>
<ReceiptDate>SALEDATE</ReceiptDate>
</getDailyReceipts>
</soap:Body>
</soap:Envelope>
ENDTEXT
XMLHTTP = STRTRAN(XMLHTTP,'APIKEY',M.APIKEY)
XMLHTTP = STRTRAN(XMLHTTP,'AGENTID',M.AGENTID)
XMLHTTP = STRTRAN(XMLHTTP,'SALEDATE',M.cSALEDATE)



oHTTP = CreateObject("Microsoft.XMLHTTP")
oHTTP.Open("POST", "https://rlisapi.myfwc.com/wsReceipts.asmx", .F.)

oHTTP.setRequestHeader('Content-Type', 'text/xml; charset=utf-8 ')
oHTTP.Send(XMLHTTP)


DO CASE
CASE oHTTP.status = 200
                XMLRESPONSE = oHTTP.ResponseText
                RELEASE oHTTP
CASE oHTTP.status = 201
                WAIT'PROCESSING PLEASE WAIT' WINDOW NOWAIT
                RELEASE oHTTP
CASE oHTTP.status = 202
                WAIT 'PROCESSING PLEASE WAIT' WINDOW NOWAIT
                RELEASE oHTTP
CASE oHTTP.status = 400
                RELEASE oHTTP
                MESSAGEBOX("RLIS BAD REQUEST ERROR",0,'CCARS')
                RETURN
CASE oHTTP.status = 401
                RELEASE oHTTP
                MESSAGEBOX("RLIS UNAUTHORIZED ERROR",0,'CCARS')
                RETURN
CASE oHTTP.status = 403
                RELEASE oHTTP
                MESSAGEBOX("RLIS FORBIDDEN ERROR",0,'CCARS')
                RETURN
CASE oHTTP.status = 404
                RELEASE oHTTP
                MESSAGEBOX("CONNECTION TO RLIS SITE NOT AVAILABLE",0,'CCARS')
                RETURN
CASE oHTTP.status = 500
                RELEASE oHTTP
                MESSAGEBOX("RLIS INTERNAL SERVER ERROR",0,'CCARS')
                RETURN
OTHERWISE
                RELEASE oHTTP
                MESSAGEBOX(oHTTP.status,0,'CCARS')
                MESSAGEBOX("RLIS INTERNAL SERVER ERROR CODE " + STR(oHTTP.status,3,0),0,'CCARS')
                RETURN
ENDCASE

MESSAGEBOX(XMLRESPONSE)

以下是错误的完整堆栈跟踪:


java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:168)
at com.sun.net.ssl.internal.ssl.InputRecord.readFully(InputRecord.java:422)
at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:460)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:863)
at       com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1188)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1215)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1199)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1014)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:230)
at com.taxcollector.ccars.service.transaction.TestSoapClient.main(TestSoapClient.java:51)

根据我过去几天的所有研究,我得出的结论是,这个错误通常是因为服务器在客户端读取完之前关闭连接造成的。

一开始,我以为是 web 服务本身有问题,但由于我能够运行 foxpro 命令并获得有效响应,所以不可能是这种情况。

我还尝试了更改 Soap UI 设置中的许多首选项,包括套接字超时。

此外,我的请求没有经过代理服务器。

非常感谢任何建议或意见!

感谢您的阅读。


下面是更新后的帖子:


这是来自 Wireshark 的捕获,简单的 ACK 被省略了。

4034    2013-07-05 10:34:04.556901000   192.168.0.106   162.209.25.202  SSLv2   178 Client Hello
4038    2013-07-05 10:34:04.669714000   162.209.25.202  192.168.0.106   SSLv3   1386    Server Hello, Certificate, Server Hello Done
4040    2013-07-05 10:34:04.880678000   192.168.0.106   162.209.25.202  SSLv3   331 Client Key Exchange
4041    2013-07-05 10:34:04.885161000   192.168.0.106   162.209.25.202  SSLv3   72  Change Cipher Spec
4042    2013-07-05 10:34:04.887886000   192.168.0.106   162.209.25.202  SSLv3   127 Encrypted Handshake Message
4045    2013-07-05 10:34:05.142999000   162.209.25.202  192.168.0.106   TCP 54  https > 58365 [RST, ACK] Seq=2769 Ack=445 Win=4584 Len=0

接着就是一系列的消息重复。

我认为这表明客户端首先发起了连接请求,服务器确认了这个请求。之后出现了客户端Hello,服务器Hello,握手协议证书,服务器Hello完成,客户端密钥交换,更改密码规范,加密握手消息,最终是来自服务器的连接重置(RST)。

我查了一下最后一帧的“专家信息”是什么意思,看起来可能是协议序列可疑,例如,序列不连续或检测到重传...

这仍然让我感到困惑!我不明白在我的代码中,或从Soap UI中可能会导致服务器发生此连接重置。而且为什么在foxpro代码中的Microsoft.XMLHTTP post不会发生...难道我的请求被分成片段发送,服务器不接受吗?

我想尝试在运行foxpro命令时进行wireshark捕获,但那台电脑上运行的是Windows 8,所以我需要先弄清楚如何以管理员身份运行它。我运行的Java测试客户端在我的Mac上,会得到连接重置。

与此同时,有人有进一步的见解吗?

1个回答

9

我看到你的所有示例都应该正常工作。

我建议你使用一些数据包跟踪软件,比如wireshark或fiddler,并检查请求/响应头。也许在请求OutputStream之前需要设置一些额外信息(UserAgent等)。

================ 更新 ======================

根据您的要求,服务器要求您启用SSLv3。 在建立连接之前使用此选项。

System.setProperty("https.protocols", "SSLv3");

在我的测试中,我尝试连接,并能够将soap消息写入OutputStream,但是我从服务器收到了500错误,这是一件好事,因为这是webservice内部故障。

现在您需要找出soap消息或消息数据的问题所在。

================ 更新2 ======================

已解决!

澄清一下,我正在使用测试编号4 (HttpUrlConnection)。

消息的第3行末尾缺少一个空格。

"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" +

应该是

"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +

原因是与xmlns:xsd定义连接在一起。

我得到了这个响应。

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soap:Body>
        <getDailyReceiptsResponse xmlns="http://api.outdoorlicensesolution.com/RLIS/">
            <getDailyReceiptsResult>
                <Receipt>
                    <OrderID>0</OrderID>
                    <TotalSaleAmount>0</TotalSaleAmount>
                    <TaxCollectorFees>0</TaxCollectorFees>
                    <OrderDate>0001-01-01T00:00:00</OrderDate>
                    <AmountToACH>0</AmountToACH>
                    <CustomerID>0</CustomerID>
                    <ErrorMessage>Invalid Logon Credentials</ErrorMessage>
                </Receipt>
            </getDailyReceiptsResult>
        </getDailyReceiptsResponse>
    </soap:Body>
</soap:Envelope>

谢谢您的建议。我已经安装了Wireshark,并尽力理解每个数据包跟踪的含义。也许您或者有更多嗅探数据包经验的人可以提供一些洞察力。此外,我之前确实向我的客户确认过请求中是否需要其他用户凭据,他告诉我不需要。我的客户并不是Web服务的所有者,而是我负责将其转换为Java Web应用程序的Fox-Pro客户端的原始作者。我正在将Wireshark的跟踪行项目添加到我的帖子中。非常感谢您的帮助! - s_urbuteit
我已经使用了你的代码,看起来没问题,而且我也能重现这个问题。可能是因为服务器端(webservice)有一些客户端验证,因为SSL连接是OK的,但是被重置了,可能是因为Web服务器无法识别客户端..? - Cristian Meneses
1
我在运行foxpro客户端时从我的电脑上运行了跟踪。一个明显的不同是,从客户端到服务器的初始“客户端Hello”消息的协议是sslv3,而从我的java客户端是sslv2,然后所有其他消息都通过sslv3发送。我想知道服务器是否认为这种不一致是可疑的... - s_urbuteit
AHA!System.setProperty("https.protocols", "SSLv3");就是简单的解决方案!我一直在尝试使用从设置为sslv3的SSLContext创建的SSLSocketFactorySSLContext context = SSLContext.getInstance("SSLv3");今天我学到了很多,感谢您的帮助!谢谢。我希望这篇文章也能帮助其他人。 - s_urbuteit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接