2009-09-15 46 views
1

我想用基于XML的协议在Java中编写客户端 - 服务器应用程序。 但我有一个很大的问题!如何通过套接字InputStream发送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(); 

skt.shutdownOutput(); 

我关闭套接字,我必须保持这方面还活着,我不能把它。

我无法发送'\ 0'因为我得到服务器中的分析错误。

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

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

+1

你该怎么办呢?你没有真正描述出了什么问题。您还没有提到解析,除了在标题... – 2009-09-15 16:02:50

+0

哦对不起:(但问题是,服务器进入死锁。等待客户端输入流关闭,但我无法关闭它。 – 2009-09-15 16:18:01

回答

4

我这个四个仔解决:

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

您不想关闭套接字的OutputStream,因为套接字只有一个OutputStream。

看起来你只需要在写入OutputStream后刷新它。

out.flush(); 

编辑:感谢您的额外信息。如果你正在读这样的插座,接收器需要知道你什么时候写完了。如果关闭套接字,InputStream只知道你已经完成了写操作。

但是既然你已经声明你不能关闭套接字,你需要另一种方式告诉接收方你已经完成了。您或者需要使用一种知道要发送的数据的特殊类型的流,或者您需要为写入/读取适当数量的数据设置合同。

将数据作为Object发送(使用ObjectOutputStream/ObjectInputStream - 也许您甚至不需要转换为XML)可能最容易。

如果您不想与Object流相关的开销,简单的解决方案是计算正在发送的数据的长度,并在发送实际数据之前发送该数字。在这种情况下,您可以使用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)); 
+0

不工作。服务器等待on:request = docBuilder.parse(connection.getInputStream()); – 2009-09-16 10:55:45

+0

我在发布您的评论后立即更新了我的答案,但我发现您找到了不同的解决方案。 – rob 2009-09-28 16:40:45

相关问题