我有一个套接字连接,我希望通过它发送 XML 消息,使用 DOM 类(DocumentBuilder
等)来构造和解析 XML 文档,但我无法弄清楚等待消息时处理关闭连接的好方法。
消息可能以任何顺序到达(即我不知道哪一端将发送下一条消息),并且我想避免任何基于 sleep()
的阻塞解决方案 - 我想学习如何做得更好。我尝试了以下设置的多种变体:
class XML {
static Message readMessage(InputStream s) {
// try/catch and setup of builder omitted for brevity
Document doc = builder.parse(s);
// Traverse the doc tree to built the Message, then return
}
static void writeMessage(Message m, OutputStream s) {
// Build a Document from the provided message
Transformer transformer = tf.newTransformer();
transformer.transform(new DOMSource(doc), new StreamResult(output));
output.write('\n');
}
}
class Connection {
Socket s;
Thread reader;
Connection(Socket s) {
this.s = s;
reader = new Thread(new Runnable() {
void run() {
while (true) {
Message m = XML.readMessage(s.getInputStream());
// Handle the message here, e.g. by dispatching UI events
}
}
});
reader.start();
}
void sendMessage(Message msg) {
XML.writeMessage(msg, s.getOutputStream());
}
void close() {
if (reader.isAlive()) {
reader.interrupt();
}
if (!socket.isClosed()) {
socket.close();
}
}
}
我可以让服务器和客户端相互连接并开始等待消息,只需在每一端使用各自的 Socket
实例化一个 Connection
即可。发送和接收消息也可以正常工作。
但是,我无法找到一种彻底关闭连接的方法。我不断遇到各种异常。确切的消息取决于上面框架中的实现细节,但据我所知,当读取线程在套接字关闭后尝试读取消息时,或者当读取线程仍在读取时套接字关闭时,它们都会出现。我总是使用上面的 close()
方法关闭连接。
由于我只是将流传递到 DOM 库,因此我无法精确控制它的读取方式。
如何正确结束连接,而不导致读取器线程出现异常?
最佳答案
我设法制作了一些真正有效的东西,即使我对这个解决方案有多丑陋感到畏缩。这就是我所做的(由于它有效,我将其作为答案发布):
InputStreamReader reader = new InputStreamReader(stream);
BufferedReader breader = new BufferedReader(reader);
String xml = breader.readLine();
InputStream newstream = new ByteArrayInputStream(xml.getBytes(Charset.forName("UTF-8")));
Document doc = builder.parse(newstream);
也就是说,我必须实例化四个额外的对象,最终得到一个与我开始的对象类型完全相同的对象,只是为了让解析器意识到它拥有整个文档。
如果有更好的方法来做到这一点,我会很乐意接受并投票支持任何描述它的答案。
关于java - 从 Socket 流读取 XML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24097855/