簡體   English   中英

從套接字流讀取XML

[英]Reading XML from Socket streams

我有一個套接字連接,我希望通過該套接字發送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);

也就是說,我不得不實例化四個額外的對象,最后得到一個與我最初使用的對象類型完全相同的對象,只是為了使解析器意識到它具有整個文檔。

如果有更好的方法,我將很樂意接受並支持所有描述此問題的答案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM