2010-04-22 41 views
0

我有一個TCP套接字客戶端從服務器接收消息(數據)。消息的類型爲長度(2字節)+數據(長度字節),由STX & ETX字符分隔。java BufferedReader的具體長度返回NUL字符

我正在使用bufferedReader檢索兩個第一個字節,解碼長度,然後再從相同的bufferedReader中讀取相應的長度並將結果放入char數組中。當我試圖從閱讀器讀取(長度)字節時,我只得到它的一部分,我的數組的其餘部分充滿「NUL」字符。我想這是因爲緩衝區尚未填滿。

char[] bufLen = new char[2]; 
_bufferedReader.read(bufLen); 

int len = decodeLength(bufLen); 

char[] _rawMsg = new char[len]; 
_bufferedReader.read(_rawMsg); 

return _rawMsg; 

我在幾個迭代的方式解決了這個問題:

  • 首先我測試了我的數組的最後一個字符:如果不是ETX我會從BufferedReader中一個接一個,直到讀取字符我會到達ETX,然後重新開始我的日常工作。 的後果是,我基本上會丟棄一條消息。

  • 然後,爲了仍然檢索該消息,我會在我的「截短」消息中發現NUL字符的第一次出現,讀取&一次存儲一個附加字符,直到我到達ETX,並將它們附加到我的「截斷」消息,確認長度是好的。

它的工作原理還可以,但我真的想有什麼東西我可以做的更好,就像如果在緩衝區中的字符總數,我需要提供閱讀它之前檢查,但無法找到合適的方式去做...

任何想法/指針?

謝謝!

回答

2

InputStream讀取方法可能會返回短讀取;您必須檢查返回值以確定讀取了多少個字符,然後繼續循環讀取,直到獲得所需的數字。該方法可能會阻止,但它只會阻止,直到某些數據可用,不一定是您請求的所有數據。

大多數人最終會寫「的readFully」的方法,比如DataInputStream類,其讀取數據的預期量,或拋出IOException:

static public int readFully(InputStream inp, byte[] arr, int ofs, int len) throws IOException { 
    int         rmn,cnt; 

    for(rmn=len; rmn>0; ofs+=cnt, rmn-=cnt) { 
     if((cnt=inp.read(arr,ofs,rmn))==-1) { 
      throw new IOException("End of stream encountered before reading at least "+len+" bytes from input stream"); 
      } 
     } 
    return len; 
    } 
1

這裏是我用於測試 樣本服務器主要RCV的結構類似於

while((chars_read = from_server.read(buffer)) != -1) 
{ 
    to_user.write(buffer,0,chars_read); 
    to_user.flush(); 
} 

實際整個服務器低於...

public static void main(String[] args) throws IOException 
    { 
     try 
     { 
     if (args.length != 2) 
      throw new IllegalArgumentException("Wrong number of Args"); 

     String host = args[0]; 
     int  port = Integer.parseInt(args[1]); 

     Socket s = new Socket(host,port); 

     final Reader from_server = new InputStreamReader(s.getInputStream()); 
     PrintWriter to_server = new PrintWriter(new OutputStreamWriter(s.getOutputStream())); 

     BufferedReader from_user = new BufferedReader(new InputStreamReader(System.in)); 
     final PrintWriter to_user = new PrintWriter(new OutputStreamWriter(System.out)); 

     to_user.println("Connected to " + s.getInetAddress() + ":" + s.getPort()); 

     Thread t = new Thread() 
     { 
      public void run() 
      { 
       char [] buffer = new char[1024]; 
       int chars_read; 
       try 
       { 
        while((chars_read = from_server.read(buffer)) != -1) 
        { 
        to_user.write(buffer,0,chars_read); 
        to_user.flush(); 
        } 
       } 
       catch(IOException e) 
       { 
        to_user.println(e); 
       } 

       to_user.println("Connection closed by server"); 
       to_user.flush(); 
       System.exit(0); 
      } 
     }; 

     t.setPriority(Thread.currentThread().getPriority() + 1); 
     t.start(); 

     String line; 
     while ((line = from_user.readLine()) != null) 
     { 
      to_server.println(line); 
      to_server.flush(); 
     } 

     //t.stop(); 
     s.close(); 
     to_user.println("Connection closed by client"); 
     to_user.flush(); 
     } 
     catch(Throwable e) 
     { 
     e.printStackTrace(); 
     System.err.println("Usage : java TCPClient <hostname> <port>"); 
     } 
    }