我的WiFi三星空调没有以标准XML格式响应。 有没有办法可以忽略第一个回应?
如果我打开SSL连接,它会响应两行:
DRC-1.00
<?xml version="1.0" encoding="utf-8" ?><Update Type="InvalidateAccount"/>
我必须回答:
<?xml version="1.0" encoding="utf-8" ?><Request Type="GetToken" />
Android中的堆栈跟踪是:
W/System.err﹕ java.net.ProtocolException: Unexpected status line: DRC-1.00
我的代码:
URL url;
URLConnection conn = null;
try {
//Create connection
url = new URL(targetURL);
// for not trusted ssl connections (https)
FakeX509TrustManager.allowAllSSL();
Log.v(TAG, "Set \"javax.net.debug\" to \"all\"");
System.setProperty("javax.net.debug", "all");
conn = url.openConnection();
conn.setReadTimeout(5000 /* milliseconds */);
conn.setConnectTimeout(5000 /* milliseconds */);
conn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
conn.setUseCaches(false);
conn.setDoInput(true);
conn.setDoOutput(true);
//Send request
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.flush();
writer.close();
os.close();
Log.i(TAG, "Response " + conn.toString());
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLReader xmlReader = parser.getXMLReader();
xmlReader.parse(new InputSource(conn.getInputStream())); // Error here
Log.v(TAG, xmlReader.toString());
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
}
答案 0 :(得分:1)
问题不在于XML。问题是三星服务器没有说真正的HTTP。
(旧)HTTP RFC定义了响应的样子:
6.1 Status-Line
The first line of a Response message is the Status-Line, consisting
of the protocol version followed by a numeric status code and its
associated textual phrase, with each element separated by SP
characters. No CR or LF is allowed except in the final CRLF sequence.
Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
"DRC-1.00"
显然不是像"HTTP/1.1 200 OK"
这样的状态行,导致一些严格的HTTP符合解析器失败。
您有两种方法可以解决此问题:
Socket
。这种受限用例的基本HTTP客户端实现起来并不复杂。你基本上只是写作&#34; GET path / from / url&#34;进入socket,然后阅读回复。 Simple java http client no server response包含一个很小的例子。要支持Https,AFAIK所需要做的就是使用SSLSocket
代替。答案 1 :(得分:1)
结束于:
try {
// Taken from: http://blog.alcor.se/index.php/2013/08/09/using-java-to-connect-with-sslsocket-trusting-all-certificates/
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[]
chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[]
chain, String authType) throws CertificateException {
}
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
}
};
// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
SSLSocketFactory sslsocketfactory = sc.getSocketFactory();
sslsocket = (SSLSocket) sslsocketfactory.createSocket(targetIp, port);
sslsocket.setKeepAlive(true);
// Sets this socket's read timeout in milliseconds.
// sslsocket.setSoTimeout(timeoutSocket);
Log.d(TAG, "Sending: " + xmlAction + xmlValue + XmlConstants.NEW_LINE);
String line;
ArrayList<String> receivedLines = new ArrayList<String>();
DataOutputStream outToServerSSL = new DataOutputStream(sslsocket.getOutputStream());
BufferedReader inFromServerSSL = new BufferedReader(new InputStreamReader(sslsocket.getInputStream()));
outToServerSSL.writeBytes(xmlAction + xmlValue + XmlConstants.NEW_LINE + XmlConstants.NEW_LINE);
while ((line = inFromServerSSL.readLine()) != null) {
receivedLines.add(line);
Log.d(TAG, "Received: " + line);
}
Log.d(TAG, "Closing tha sizzle");
inFromServerSSL.close();
outToServerSSL.close();
return ParseXmlForStatusCode(receivedLines);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (sslsocket != null) {
try {
sslsocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}