Java 如何通过socket InputStream发送XML数据

Java 如何通过socket InputStream发送XML数据,java,xml,sockets,stream,Java,Xml,Sockets,Stream,我正试图用Java编写一个基于XML协议的客户机-服务器应用程序。 但是我有一个大问题 请参阅客户端代码的这一部分: InputStream incoming = skt.getInputStream(); //I get Stream from Socket. OutputStream out = skt.getOutputStream(); [...] XMLSerializer serializer = new XMLSerializer(); //This create an XML

我正试图用Java编写一个基于XML协议的客户机-服务器应用程序。 但是我有一个大问题

请参阅客户端代码的这一部分:

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();

我关闭了插座,必须保持此连接处于活动状态

我无法发送'\0',因为我在服务器中遇到分析错误

我怎么做?我可以在不关闭套接字的情况下“关闭”输出流吗

已解决
我使用高级流手势创建了新类XMLStreamOutput和XMLStreamInput。

您不想关闭套接字的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));

我已经解决了这四个问题:

(一)

(二)

(三)

(四)


你怎么能做什么?你还没有真正描述出哪里出了问题。除了在标题中,您还没有提到解析…哦,对不起:(但是问题是服务器处于死锁状态。等待客户端inputstream关闭,但我无法关闭它。不工作。服务器等待:request=docBuilder.parse(connection.getInputStream());在您发表评论后,我立即更新了我的答案,但我发现您找到了不同的解决方案。:)
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));
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();
 }
}
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();
 }
}
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;
 }

}
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;
 }
}