[英]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.