2009-09-15 47 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

相關問題