簡體   English   中英

如何通過套接字InputStream發送XML數據

[英]How to send XML data through socket InputStream

我正在嘗試使用基於XML的協議用Java編寫客戶端服務器應用程序。 但是我有一個大問題!

參見客戶端代碼的這一部分:

InputStream incoming = skt.getInputStream(); //I get Stream from Socket.
OutputStream out = skt.getOutputStream();

[...]

XMLSerializer serializer = new XMLSerializer();
//This create an XML document.
tosend = WUTPClientWriter.createMessage100(projectid, cpuclock, cpunumber);
serializer.setOutputByteStream(out);
serializer.serialize(tosend);

此時服務器陷入僵局。 它等待EOF,但我無法發送它,因為如果使用

out.close();

要么

skt.shutdownOutput();

我關閉了套接字,並且必須保持此連接有效。

我無法在服務器中收到“解析錯誤”,因此無法發送“ \\ 0”。

我該怎么做? 我可以在不關閉套接字的情況下“關閉”輸出流嗎?

解決方法我創建了具有高級Stream手勢的新類XMLStreamOutput和XMLStreamInput。

我已經解決了這四個課程:

1)

public class XMLOutputStream extends  ByteArrayOutputStream {

 private DataOutputStream outchannel;

 public XMLOutputStream(OutputStream outchannel) {
     super();
     this.outchannel = new DataOutputStream(outchannel);
 }

 public void send() throws IOException {
     byte[] data = toByteArray();
     outchannel.writeInt(data.length);
     outchannel.write(data);
     reset();
 }
}

2)

public class XMLSender {

 public static void send(Document tosend, OutputStream channel) throws   TransformerConfigurationException, IOException {
     XMLOutputStream out = new XMLOutputStream(channel);

     StreamResult sr = new StreamResult(out);
     DOMSource ds = new DOMSource(tosend);
     Transformer tf = TransformerFactory.newInstance().newTransformer();

     try {
         tf.transform(ds, sr);
     } catch (TransformerException ex) {
         Logger.getLogger(XMLSender.class.getName()).log(Level.SEVERE, null, ex);
     }

     out.send();
 }
}

3)

public class XMLInputStream extends ByteArrayInputStream {

 private DataInputStream inchannel;

 public XMLInputStream(InputStream inchannel) {
     super(new byte[2]); 
     this.inchannel = new DataInputStream(inchannel);
 }

 public void recive() throws IOException {
     int i = inchannel.readInt(); 
     byte[] data = new byte[i];
     inchannel.read(data, 0, i); 
     this.buf = data; 
     this.count = i;
     this.mark = 0;
     this.pos = 0;
 }

}

4)

public class XMLReceiver {

 public static Document receive(InputStream channel) throws ParserConfigurationException, TransformerConfigurationException, IOException, SAXException {

     DocumentBuilderFactory docBuilderFact = DocumentBuilderFactory.newInstance();
     DocumentBuilder docBuilder = docBuilderFact.newDocumentBuilder();
     Document request = null;


     XMLInputStream xmlin = new XMLInputStream(channel);

     xmlin.recive();

     request = docBuilder.parse(xmlin);

     return request;
 }
}

您不想關閉套接字的OutputStream,因為套接字只有一個OutputStream。

看起來您只需要在寫入后刷新OutputStream。

out.flush();

編輯:感謝您的額外信息。 如果您正在以這種方式讀取套接字,那么接收器需要知道何時完成寫入。 如果關閉套接字,InputStream僅知道您已完成編寫。

但是,由於您已經聲明無法關閉套接字,因此需要另一種方式告訴接收方您已完成操作。 您可能需要使用一種特殊的流類型,該流類型知道要發送的數據,或者您需要設置合同以寫入/讀取適當數量的數據。

將數據作為對象發送(使用ObjectOutputStream / ObjectInputStream-也許甚至不需要轉換為XML)可能是最簡單的。

如果您不希望與對象流相關的開銷,那么簡單的解決方案是計算要發送的數據的長度,並在發送實際數據之前發送該數字。 在這種情況下,您可以使用DataOutputStream / DataInputStream。 發送要讀取的字節數,然后發送數據。 在接收方,讀取該數字,然后將給定的字節數讀取到一個臨時變量中,並將其提供給DocumentBuilder.parse(InputStream)。

在發送端,您可以這樣做:

DataOutputStream out = new DataOutputStream(s.getOutputStream());
ByteArrayOutputStream baos = new ByteArrayOutputStream();

XMLSerializer serializer = new XMLSerializer();
serializer.setOutputByteStream(baos);
tosend = WUTPClientWriter.createMessage100(projectid, cpuclock, cpunumber);
serializer.serialize(tosend);

out.writeInt(baos.size());
out.write(baos.toByteArray());

out.flush();

然后在接收端,執行以下操作:

DataInputStream in = new DataInputStream(s.getInputStream());

int len = in.readInt();
byte[] xml = new byte[len];
in.read(xml, 0, len);

Document doc = builder.parse(new ByteArrayInputStream(xml));

暫無
暫無

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

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