【发布时间】:2017-03-01 19:24:03
【问题描述】:
我正在将 Applet 转换为桌面应用程序,内部程序的服务之一包括一个 SOAP 客户端,旨在将信息发送到远程服务器。这是负责这个过程的一段代码:
package my.package.app.utils;
import my.package.app.main.MainClass;
import my.package.app.org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.logging.Level;
import java.util.logging.Logger;
public class SoapClient {
public static JSONObject callMethod(String path, String method, Object... args) {
HttpURLConnection connection = null;
String data = null;
try {
data = parseXML(method, args);
MainClass.debug("Making http POST connections to : " + path);
URL u = new URL(path);
URLConnection uc = u.openConnection();
connection = (HttpURLConnection) uc;
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("SOAPAction", method);
connection.setUseCaches(false);
OutputStream out = connection.getOutputStream();
Writer wout = new OutputStreamWriter(out);
wout.write(data);
wout.flush();
wout.close();
InputStream in = connection.getInputStream();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(in);
doc.getDocumentElement().normalize();
NodeList childs = doc.getElementsByTagName("return");
String responseText = childs.item(0).getTextContent();
if ("false".equals(responseText)) {
return null;
}
JSONObject response = new JSONObject(responseText);
in.close();
return response;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
private static String parseXML(String method, Object... args) {
StringBuilder xml = new StringBuilder();
xml.append(XMLTemplates.soapHeader);
xml.append("<ns1:");
xml.append(method);
xml.append(">");
for (int i = 0; i < args.length; i++) {
String dataType = "xsi:type=\"xsd:string\"";
xml.append("<param");
xml.append(i);
xml.append(" ");
if (args[i] instanceof Integer) {
dataType = "xsi:type=\"xsd:integer\"";
}
if (args[i] instanceof Double) {
dataType = "xsi:type=\"xsd:decimal\"";
}
if (args[i] instanceof Boolean) {
dataType = "xsi:type=\"xsd:boolean\"";
}
xml.append(dataType);
xml.append(">");
xml.append(String.valueOf(args[i]));
xml.append("</param");
xml.append(i);
xml.append(">");
}
xml.append("</ns1:");
xml.append(method);
xml.append(">");
xml.append(XMLTemplates.soapFooter);
return xml.toString();
}
}
当使用 callMethod 时,它会收到一个 path 字符串,其中的 URL 采用 HTTPS 协议,如下所示:“https://fileserver.myserver.net:9000/lf_soap_document_server_main.php”。
使用该 URL 运行 callMethod 时,applet 的 Java 控制台会显示以下内容:
18:15:45.476-DEBUG: Making http POST connections to : https://fileserver.myserver.net:9000/lf_soap_document_server_main.php
network: Connecting https://fileserver.myserver.net:9000/lf_soap_document_server_main.php with proxy=DIRECT
network: Connecting http://fileserver.myserver.net:9000/ with proxy=DIRECT
并且该过程成功完成。
但是,当从桌面应用程序版本执行具有相同信息的同一段代码时,会发生以下情况:
18:28:29.991-DEBUG: Making http POST connections to : https://fileserver.myserver.net:9000/lf_soap_document_server_main.php
network: Connecting https://fileserver.myserver.net:9000/lf_soap_document_server_main.php with proxy=DIRECT
network: Connecting socket://fileserver.myserver.net:9000 with proxy=DIRECT
java.net.ConnectException: Connection timed out: connect
当调用 OutputStream out = connection.getOutputStream(); 时会出现问题。请注意,日志消息将 URL 的协议从 https:// 更改为 socket://,并且似乎还删除了最后一个斜杠 (/)。
这是完全的例外:
java.net.ConnectException: Connection timed out: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at sun.security.ssl.SSLSocketImpl.connect(Unknown Source)
at sun.net.NetworkClient.doConnect(Unknown Source)
at sun.net.www.http.HttpClient.openServer(Unknown Source)
at sun.net.www.http.HttpClient.openServer(Unknown Source)
at sun.net.www.protocol.https.HttpsClient.<init>(Unknown Source)
at sun.net.www.protocol.https.HttpsClient.New(Unknown Source)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.getNewHttpClient(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection$6.run(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection$6.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessController.doPrivilegedWithCombiner(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.access$100(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection$8.run(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection$8.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessController.doPrivilegedWithCombiner(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(Unknown Source)
at my.package.app.utils.SoapClient.callMethod(SoapClient.java:42)
at my.package.app.services.scanner.LFScanner$SoapUpload.run(LFScanner.java:746)
桌面应用程序使用 Jetty 创建到安全 websocket 服务器的连接,并在用户的机器中创建本地 websocket 服务器,但是它们都没有与发生问题的 SoapClient 类有业务。
我已经测试了为连接设置 5 分钟超时并读取到 HttpURLConnection 实例,但问题在不到一分钟的时间内一直在桌面应用程序上发生。
我使用 1.8.0_111-b14 作为运行时在 Windows 10 机器上执行程序(小程序和桌面应用程序),64 位。
我需要知道这段代码是否有任何问题,或者这里是否缺少设置以防止这种情况发生。
非常感谢任何帮助。
谢谢。
【问题讨论】:
-
您是否使用代理从桌面访问互联网?如果是这样,您的 Java 代码也需要使用它。
-
不,我没有使用代理。
-
还是防火墙?你能在网络浏览器中打开网址吗?
-
是的。我可以毫无问题地在浏览器上打开 URL。
标签: java sockets https applet network-protocols