2015-07-13 146 views
1

我的程序基本上是:Server客戶端通信的Outputstreams失敗

  1. 客戶端發送一個字符串到服務器,

  2. 根據此字符串,服務器創建一個ArrayList,

  3. ArrayList被髮送回客戶端。

這到底是怎麼失敗的是:

客戶端後發送一個字符串,服務器接收它,並沒有做任何事情。在這個時候,客戶端繼續工作並獲得NullPointer。

客戶端:

public static ArrayList<String> sendStringToServer(String report) { 

    Socket socket; 

    ArrayList<String> fieldsList = new ArrayList<String>(); 

    try { 

     socket = new Socket("localhost", 2345); 

     OutputStream os = socket.getOutputStream(); 
     PrintStream ps = new PrintStream(os, true); 

     ps.println(report); 
     ps.flush(); 

     //Here the debugger should stop and wait for server to create a List 

     //at this point there is no answer, code breaks 
     ObjectInputStream objectInput = new ObjectInputStream(socket.getInputStream()); 

     Object object = objectInput.readObject(); 
     fieldsList = (ArrayList<String>) object; 

     socket.close(); 

     return fieldsList; 

    } catch (IOException e1) { 

     e1.printStackTrace(); 
    } catch (Exception e) { 

     e.printStackTrace(); 
    } 
    return null; 
} 

}

服務器端:

public class Server { 

private ServerSocket serverSocket; 
private Socket clientSocket; 
private String telegram; 
private StringBuilder telegramSB; 

public static void main(String[] args) throws IOException, JRException { 

    new Server(); 
} 
public Server() { 

    try { 
     serverSocket = new ServerSocket(2345); 

     while (true) { 

      clientSocket = serverSocket.accept(); 
      InputStream is = clientSocket.getInputStream(); 
      InputStreamReader isr = new InputStreamReader(is); 
      BufferedReader br = new BufferedReader(isr); 

      try { 

       //debugger goes to here and then stops 
       telegram = br.readLine(); 

       int counter = 0; 

       boolean startSeq = false; 

       for (char ch : telegram.toCharArray()) { 

        if (counter == 0 && ch == '/') { 

         startSeq = true; 
        } 

        if (startSeq == true) { 

         telegramSB = new StringBuilder(); 
         telegramSB.append(ch); 
        } 

        if (ch == '\n') { 

         if (telegram.length() < 255) { 

          sendListWithFields(); 

         } else { 

          new Launcher(telegram).run(); 
         } 
        } 
        counter++; 
       } 
      } catch (JRException e) { 

       e.printStackTrace(); 

      } catch (IOException e) { 

       e.printStackTrace(); 

      } 
     } 
    } catch (IOException e) { 

     System.out.println(e); 
    } 
} 
+0

你發送行尾(EOF)字符/ s嗎? –

+0

@eyp是的,我做但我的程序永遠不會到達那裏。它讀取bufferedReader然後停止。 –

回答

0

在這裏,我的猜測是對的BufferedReader等待填滿其緩衝區和你的避風港沒有發送足夠的數據來做到這一點,並返回,所以它等待更多的數據來臨呃,永遠不會(因爲你的客戶停止寫作,並開始閱讀)。您可以通過將更多數據加載到客戶端上的OutputStream並將其刷新來暫時測試此理論。

如果上面是這種情況,那麼你可能不想使用BufferedReader,但你在這裏還有其他問題,這也意味着你可能想避免使用PrintStream和BufferedReader進行通信和序列化。例如,兩個不同機器和JVM上的默認字符編碼可能不同。當你創建你的PrintStream和InputStreamReader時,你並沒有指定一個字符編碼,所以它們最終可能不匹配,而且你寫的字符串(包括換行符)最終會被遠程端完全不同的理解,這也可能是這是阻止它的原因(客戶端以一種方式對換行符進行編碼,但服務器期望它以完全不同的方式進行編碼),但我認爲不太可能。

如果你不這樣做使用PrintStream的話,我會使用DataOutputStream/DataInputStream所建議改爲:

//Client 
BufferedOutputStream bufout = new BufferedOutputStream(socket.getOutputStream()); 
DataOutputStream dout = new DataOutputStream(bufout); 
dout.writeUTF(report); 
dout.flush(); 

//Server 
BufferedInputStream bufin = new BufferedInputStream(socket.getInputStream()); 
DataInputStream din = new DataInputStream(bufin); 
String report = din.readUTF(); 

你仍然從BufferedIn/OutputStreams得到緩衝,因此這將是高性能,但數據輸入/ OutputStreams將管理可變長度對象的終止 - 它們將發送一個字符串前綴的長度來告訴另一方準確讀取多少字節,因此您不需要使用特殊字符來終止您所寫的字符串,並且這也意味着你的String的內容並不重要。在上面的例子中,即使它在工作,如果你的字符串中有一個換行符,服務器也會讀取直到第一個換行符,而不是你發送的字符串的末尾,這會使它們不同步以用於下一次發送/沿着該流接收。

使用write/readUTF還指定了編碼(UTF-8),因此不存在任何不匹配。