2013-11-28 115 views
-1

我試過這個,但沿線的某處我無法讀取服務器的響應。 (響應以XML格式)。通過java套接字發送xml字符串的最佳方式是什麼?

我已經讀過,寫入套接字需要緩衝,因爲字符串破損。不知何故,當我使用jaxb unmarshaller時,我發現這是真的,並且它報告了一個SAX EOF異常,這意味着讀取的xml不完整。

請問我如何緩衝寫入和緩衝區讀取正確?

StringBuilder sb = new StringBuilder(); 
sb.append("<estel>"); 
sb.append("<header><requesttype>").append(hd.getRequestType()).append("</requesttype></header>"); 
sb.append("<request>"); 
sb.append("<agentcode>").append(rq.getAgentCode()).append("</agentcode>"); 
sb.append("<pin>").append(rq.getPin()).append("</pin>"); 
sb.append("<destination>").append(rq.getDestination()).append("</destination>"); 
sb.append("<agenttransid>").append(rq.getAgentTransId()).append("</agenttransid>"); 
sb.append("<vendorcode>").append(rq.getVendorCode()).append("</vendorcode>"); 
sb.append("<amount>").append(rq.getAmount()).append("</amount>"); 
    sb.append("<productcode>").append(rq.getProductCode()).append("</productcode>"); 
    sb.append("<comments>").append(rq.getComments()).append("</comments>"); 
    sb.append("<clienttype>").append(rq.getClientType()).append("</clienttype>"); 
sb.append("</request></estel>"); 


    Socket socket = new Socket("41.206.23.21",7101); 
    OutputStream os = socket.getOutputStream(); 
    InputStream in = socket.getInputStream(); 

    OutputStream buf = new BufferedOutputStream(os);  
    out = new OutputStreamWriter(buf); 

    System.out.printf("\nxml is %s",sb.toString()); 
    System.out.print("\n--------writing--to--socket-----"); 
    out.write(sb.toString()); 
    out.flush(); 

    //read response 
    InputStream bui = new BufferedInputStream(in); 
    rd = new InputStreamReader(bui); 
    System.out.print("\nxml response"+rd.toString()); 

    in.close(); 
    out.close(); 
    socket.close(); 
+0

你說的僅僅適用於HTTP POST請求。普通插座有一個直接的行爲。 – jboi

回答

0

您通過套接字發送XML,但服務器端不回答。爲了100%確定會發生什麼,我們需要服務器代碼和服務器錯誤消息。到目前爲止,我看到兩件事情,你可以做:

  1. 在寫和沖洗的XML,你可以調用socket.shutdownOutput()。這將EOF發送到服務器,表明沒有更多可讀的內容。最新的服務器應該知道,它必須處理XML併產生結果。

  2. 您通過byte流發送字符串char。希望服務器能夠像客戶端發送它一樣瞭解。由於希望在編程中並沒有什麼幫助,所以你應該像下面這樣包裝輸出流:Writer writer = new OutputStreamWriter(socket.shutdownOutput(), "UTF-8");並且執行寫入操作和寫入器刷新。請注意,您需要做的對輸入流服務器端相同(如包裝與讀卡器「UTF-8」)

+0

是socket.shutDownOutput()對於xml是強制性的嗎?>我認爲是因爲這種穩定程序,但我似乎無法讀取即時消息寫入響應。仍然沒有解決 –

+0

您傳輸文本的方式(這裏是通過套接字)與您傳輸的內容無關(這裏是一個XML文檔)。正如我所說的,當服務器沒有響應你的XML,比服務器掛起。很可能是因爲服務器仍然在等待更多輸入或者不能識別,XML結束了。這就是爲什麼我建議在輸出流中發送EOF。但是,因爲我們沒有關於服務器的信息,所以可能是其他問題。如果您需要更多幫助,則需要提供有關服務器的更多信息。 – jboi

+0

說出響應字符串是

無效請求<\request><\header><\estel>當我遠程登錄,然後使用插座和與JAXB解組我也得到這種反應,你得到這個反應,只有當你不發送正確的XML格式 –

0

請減少您的問題到正在運行的一段代碼,顯示錯誤。發佈一些甚至不能編譯的代碼,並不能真正幫助你理解你的問題。即使在一個方法中嵌入這段代碼並導入java.io的東西之後,還有4個(!)未聲明的變量:hd, rq, out and rd

爲了幫助您的問題,並回答大家的提問:

  1. 你並不需要使用一個緩衝的作家,你只需要確保你寫的一切你想要寫(刷新或關閉之後流)。當客戶端(接收者)嘗試解釋數據之前,只要字節可用,就必須從該數據流中讀取數據。

  2. 如果你想實現一個不同的協議,你當然必須讀/寫,直到某個標記或任何東西表明你的傳輸完成。但對於這個問題,我假設你只想傳輸一組XML數據。

對於書寫,您可以使用簡單的OutputStream一次性編寫字符串。 像這樣的代碼會做的工作:

StringBuilder sb = new StringBuilder(); 
//... 
Socket socket = new Socket("41.206.23.21", 7101); 
OutputStream os = socket.getOutputStream(); 
os.write(sb.toString().getBytes()); 
os.flush(); 

讀取,你也可以使用一個簡單的InputStream。爲了確保你得到了一切,你通常應該讀取數據並將它們全部寫入到一箇中間字節數組中,然後您可以將其轉換回字符串。一個通用的方法可能是這樣的:

String read(InputStream in) throws IOException { 
    byte[] buffer = new byte[8192]; 
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    int got; 
    while ((got = in.read(buffer)) > -1) { 
     out.write(buffer, 0, got); 
    } 
    byte[] data = out.toByteArray(); 
    String result = new String(data); 
    return result; 
    } 

請記住,此方法既不關閉流,也不處理異常。

+0

@Matthiaas我實際上已經嘗試過你的版本,但是它掛起@寫入套接字開始的地方,整個代碼都在try塊內,IOException捕獲它。 –

+0

在哪一點?你可以在兩個程序中完成,或者至少在兩個線程中完成,是的? – Matthias

+0

我只是用一個主要方法和一個try塊封裝讀取輸出流和inputstream的代碼,它看起來像是xml字符串,你可以做socket.shutDownOutput()。爲了阻止掛起,似乎服務器期待更多的數據。 –

相關問題