2010-08-16 24 views
2

我的問題類似於這篇文章。但是我不會發送數據包長度而不是最後一個0字節。 Most efficient way to read in a tcp stream in Java如何讀取java流,直到達到某個字節

所以我想知道如何編碼的東西,會。

目前,我只是用

this.socketIn = new BufferedReader(new InputStreamReader(this.socket.getInputStream())); 
String line = this.socketIn.readLine(); 

如果包是越來越發送,而你是垃圾郵件的包它要算這還沒到作爲一個完全讀行的數據包,但它是不完整的,弄亂了整個協議。

在我的協議中,如果數據包最終合併/堆疊在一起,每個數據包都以0字節(0x00)結尾,以確定單個數據包的結束。

所以我試圖做的確實是不斷讀取套接字流,直到達到0x00來指示數據包已完全製作並準備好處理..當然還有某種安全性(超時最好是我相信)來確定數據包是垃圾郵件,因爲它沒有在特定時間幀的0字節中結束,比如說5秒。

我該怎麼做呢?

PS> 我沒有使用NIO框架,而是每個連接套接字只有一個常規線程,我不想切換到NIO,因爲使用完全不同的全局線程處理更新併發送數據非常困難隨機用戶的特定更新(不廣播)。

這是我到目前爲止所嘗試的。

String line = ""; 
    int read; 
    long timeOut = System.currentTimeMillis(); 
    while(true) { 
     read = this.socketIn.read(); 
     if (read == -1 || read == 0 || (System.currentTimeMillis()-timeOut) > 5000) 
      break; 
     line += read 
    } 
+1

到目前爲止您嘗試過什麼問題?順便說一句,使用Socket.setSoTimeout(),不要發展自己的。 – EJP 2010-08-16 23:58:53

+0

哈哈謝謝EJP我不知道tmeout命令存在。 – SSpoke 2010-08-17 00:37:46

回答

5

下面是一個使用setSocketTimeout來處理「慢客戶端/拒絕服務」場景的草圖。

this.socket.setSoTimeout(5000); 
BufferedReader br = new BufferedReader(
    new InputStreamReader(this.socket.getInputStream())); 
StringBuilder sb = new StringBuilder(); 
try { 
    int ch ; 
    while ((ch == br.read()) != -1) { 
     if (ch == 0) { 
      String message = sb.toString(); 
      // process message 
      sb.setLength(0); 
     } else { 
      sb.append((char) ch); 
     } 
    } 
} catch (InterruptedIOException ex) { 
    System.err.println("timeout!"); 
    ... 
} finally { 
    br.close(); 
} 

我覺得還可以通過創建套接字對象調用socket.close(),如果它檢測到讀線程沒有得到任何數據,第二個線程來實現(殘酷)套接字超時。但是鑑於更簡單的setSoTimeout()方法,這是一個重量級的方法。

+0

k經過研究,我發現StringBuffer更快,然後使用常規對象concat和StringBuilder,速度更快。 還有更多的研究發現沒有.clear()命令,所以我假設你使用一些不同的界面,但看到你從來沒有真正編譯它,你犯了一個錯誤,我想.. 但我找到了一個解決方案,我想我是使用你的方法清除你只需使用sb.setLength(0);正確? – SSpoke 2010-08-17 04:10:17

+0

@SSpoke - 我的錯誤...糾正。這就是爲什麼我將代碼稱爲「草圖」的原因。 – 2010-08-17 04:24:53

0

我應該使用StringBuilder嗎?或者像EJP寫的那樣建立我自己的。哪個更快?

  String line = ""; 
      int read; 
      //long timeOut = System.currentTimeMillis(); 
      this.socket.setSoTimeout(5000); 
      while(this.socket.isConnected()) { 
      read = this.socketIn.read(); 
      if (read == -1) 
       throw new IOException("Insufficient data/timeout)"); 
      else if(read == 0) 
       break; 
      line += (char)(read & 0xFF); 
      } 
2
InputStreamReader isr = new InputStreamReader(socket.getInputStream()); 
BufferedReader in = new BufferedReader(isr); 
String line = ""; 
String response = ""; 
while ((line = in.readLine()) != null) { 
    System.out.println(line); 
    response = response + line + "\n"; 
    if (in.ready() == false) { 
     break; 
    } 
} 

訣竅是屬於的BufferedReader就緒功能。你需要檢查它是否準備好,如果不是剛剛離開循環。

相關問題