java - 从 Socket 流读取 XML

标签 java multithreading sockets

我有一个套接字连接,我希望通过它发送 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/

相关文章:

java - 多线程 - 杀死一个线程及其所有子进程

c# - 从设备驱动程序重新抛出套接字异常

java - 如何在 jOOQ 中使用行值表达式?

java - 如何循环调用函数显示文件之间的父子关系

multithreading - 如何为当前线程创建协程Dispatcher?

c++ - 使用 Boost.asio 并行 Ping(ICMP) 多个目的地

java - 跨网络在java实例之间同步变量

java - 缺少 run() 方法?

java - 通过套接字传输文件时出现 IndexOutOfBoundsException。紧急数据传输控制

java - 如何使用套接字将文件从服务器端传输到客户端?