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