2017-02-09 131 views
-2

我到處搜索包括這裏尋找可能的解決方案,並嘗試了一些我發現沒有成功的答案。無法讀取套接字響應C服務器到Java客戶端

我實現了一個簡單的Java tcp套接字客戶端。客戶端在一臺Java服務器上工作得非常好,但是我仍然遇到問題,從C編碼的服務器接收到響應。 服務器似乎正確地處理了事務,並相應地發送了回覆。問題在於客戶端能夠接收到回覆的傳入流。 這是我最初的實現:

 String msg_out = message; 
     String reply; 

     //the stream object to transmit message to server 
     DataOutputStream outStream = new DataOutputStream(clientSocket.getOutputStream()); 

     outStream.writeBytes(msg_out + '\n'); 
     outStream.flush(); 

     //try to break away from locked read 
     //clientSocket.setSoTimeout(10000); 

     //initial implementation 
     //the object to receive reply server 
     BufferedReader replyStream = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); 
     reply = replyStream.readLine(); 

     System.out.println("Reply from "+ host + ":" + port + " -> " + reply); 

我下載Wireshark的,並用它來監視相應端口的服務器套接字監聽客戶端和服務器之間的TCP數據包流量。我在其他主題類似的主題中看到了多個建議,但不幸的是我無法得到任何這些解決方案爲我工作。我發現包含回覆的數據包的標誌值設置爲PSH(因爲在接收時不會緩衝流,立即進行處理)。我認爲Java客戶端試圖緩衝回覆導致連接重置(出現在發生的下一個失敗包中的RST),因爲這個標誌。我試着用這個實現我在一個線程中測試在這裏試圖讀取字節,但無濟於事回覆字節:

try { 
      DataInputStream in = new DataInputStream(clientSocket.getInputStream()); 
      int bytesRead = 0; 
      byte[] messageByte = new byte[1000]; 
      boolean end = false; 
      String messageString = ""; 
      messageByte[0] = in.readByte(); 
      messageByte[1] = in.readByte(); 
      ByteBuffer byteBuffer = ByteBuffer.wrap(messageByte, 0, 2); 

      int bytesToRead = byteBuffer.getShort(); 
      System.out.println("About to read " + bytesToRead + " octets"); 

      //The following code shows in detail how to read from a TCP socket 

      while(!end) 
      { 
       bytesRead = in.read(messageByte); 
       messageString += new String(messageByte, 0, bytesRead); 
       if (messageString.length() == bytesToRead) 
       { 
        end = true; 
       } 
      } 


      System.out.println("Server Reply: " + messageString); 
     } catch (Exception e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

我沒有訪問源代碼爲C服務器,但它的開發者發誓要我認爲問題不在他的最後,我相信他。我也知道他不能對它進行更改,因爲它可以與所有其他正在使用的客戶端架構一起使用,我編碼的那個恰好是與此C服務器交互的唯一Java客戶端。在我的實現中是否有錯誤,或者是否有其他實現可以用於以更加傻瓜的方式讀取答覆流?

這裏的嘗試運行的客戶端/服務器通訊過程的結果:

[2/10/17 14:23:49:658 EST] 00000031 SystemOut  O Outgoing transaction message:C00052!GDT43000KU!01!D-10!G-11!NORMAL!|     
[2/10/17 14:23:49:658 EST] 0000011e SystemOut  O Buffersize in stream:8192 
[2/10/17 14:23:49:737 EST] 0000011e SystemOut  O About to read 12336 octets 
[2/10/17 14:23:49:737 EST] 0000011e SystemErr  R java.net.SocketException: Connection reset 
[2/10/17 14:23:49:737 EST] 0000011e SystemErr  R  at java.lang.Throwable.<init>(Throwable.java:67) 
[2/10/17 14:23:49:737 EST] 0000011e SystemErr  R  at java.net.SocketInputStream.read(SocketInputStream.java:118) 
[2/10/17 14:23:49:737 EST] 0000011e SystemErr  R  at java.io.DataInputStream.read(DataInputStream.java:94) 
[2/10/17 14:23:49:737 EST] 0000011e SystemErr  R  at com.gf.btv.RTDLTSS.domain.LTSSClient.TCPClientRequest(LTSSClient.java:141) 
[2/10/17 14:23:49:737 EST] 0000011e SystemErr  R  at com.gf.btv.RTDLTSS.helper.LTSSClientThread.run(LTSSClientThread.java:147) 
[2/10/17 14:23:49:737 EST] 0000011e SystemErr  R  at java.lang.Thread.run(Thread.java:736) 
+0

你確定他們發送Big Endian嗎?一些C程序假設小端, –

+1

*當您嘗試運行客戶端時實際發生了什麼? – immibis

+1

服務器使用什麼協議來回復?它是否在字節級記錄?如果你不知道服務器期望它做什麼,你怎麼可能知道你的客戶是否做對了? (你有協議文檔嗎?或者你需要對協議進行反向工程?如果你有協議文檔,分享它。如果你需要對協議進行逆向工程,請告訴我們服務器發送給你的字節,這樣我們可以嘗試幫助你) –

回答

0

的RST沒有什麼關係的PSH或緩衝的讀者,但如果你需要閱讀二進制讀者不合適。 RST表示對方在您讀取連接之前關閉了連接,這表明您正在使用錯誤的協議。請求協議是基於行的,但響應協議是基於長度字前綴的,這是不可信的。一個或另一個,或別的東西。

如果確定它確實是一個長字前綴協議,試試這個:

int messageLength = in.readShort(); 
byte messageBytes = new byte[messageLength]; 
in.readFully(messageBytes); 
// etc. 

但你需要實際的協議的確認。猜測不會讓你在那裏。

+0

我會再次問一次,以確保我們知道這種情況,但我真的不認爲這個問題與此有關。 – rocklandcitizen

+0

你應該再次詢問以確保你知道*協議。*你已經在這裏使用了兩個,並且這兩個都是正確的。很可能*既不*也是正確的。 – EJP

+0

我注意到假設'短'(2字節int)值是12336,這是兩個字節的值,每個字節包含ASCII字符'0'。我懷疑服務器實際上是以字符形式發送長度或其他值。 –

相關問題