2012-03-15 208 views
1

我有這樣的客戶機/服務器應用程序,有時完全由客戶端應用程序凍結當我嘗試通過套接字Java客戶端應用程序凍結

public Client client = new Client(); 
petriNetList = client.query(client.actionLoadPetriNetList, MainWindow.loginUsername); 

這裏發送的對象是客戶端的代碼

public class Client { 
    public static Socket kkSocket = null; 
    public static PrintWriter out = null; 
    public static BufferedReader in = null; 
    public static BufferedReader stdIn = null; 
    public static OutputStream outputStream = null ; 
    public static ObjectOutputStream objectOutputStream = null ; 
    public static InputStream inputStream = null ; 
    public static ObjectInputStream objectInputStream = null ; 


    public String actionSavePetriNet = "SAVE PETRI NET START"; 



    /* 
    * Save petri net to server 
    * 
    * @param action identifies query 
    * @param petriName name of the petri net 
    * @param username username 
    * @param xml content of the petri net 
    * 
    * @return int response form server 
    */ 
public int query (String action,String petriName,String username,String xml) throws IOException { 



    int size ; 
    int result = 0; 
    connect(); 
    if (action.equals(actionSavePetriNet)) { 

     out.println(action); // save petri net 
     out.println(petriName); //petri net name 
     out.println(username); //username 
     System.out.println("(Client:)" + xml); 
     objectOutputStream.writeObject(xml); //send object over the network 
     System.out.println("Dostali sme sa sem ?"); 
     result = Integer.parseInt(in.readLine()); //read response from server 
    } 

     disconnect(); 
     return result; 
}  


    /* 
    * connect to server 
    * TODO: ADD hostname and port as parameter 
    */ 
    public static void connect() throws IOException { 
    try { 
      kkSocket = new Socket("osiris-PC", 4444); 
      out = new PrintWriter(kkSocket.getOutputStream(), true); 
      in = new BufferedReader(new InputStreamReader(kkSocket.getInputStream())); 
     } catch (UnknownHostException e) { 
      System.err.println("Don't know about host: taranis."); 
      System.exit(1); 
     } catch (IOException e) { 
      System.err.println("Couldn't get I/O for the connection to: taranis."); 
      System.exit(1); 
     } 

     stdIn = new BufferedReader(new InputStreamReader(System.in)); 

      outputStream = kkSocket.getOutputStream(); 
      objectOutputStream = new ObjectOutputStream(outputStream); 

      inputStream = kkSocket.getInputStream(); 
      objectInputStream = new ObjectInputStream(inputStream); 

    } 

    /* 
    * Disconnect from server 
    * close all input/output streams 
    * 
    */ 
    public static void disconnect() throws IOException { 
     out.close(); 
     in.close(); 
     stdIn.close(); 
     objectOutputStream.close(); 
     outputStream.close(); 
     objectInputStream.close(); 
     inputStream.close(); 
     kkSocket.close(); 

    } 
} 

,這是服務器的代碼

public class PetriServer { 
    public static Protocol kkp = new Protocol(); 

    public static InputStream inputStream = null ; 
    public static ObjectInputStream objectInputStream = null ; 
    public static OutputStream outputStream = null ; 
    public static ObjectOutputStream objectOutputStream = null ; 



    public static void main(String[] args) throws IOException, ClassNotFoundException { 
     kkp.loadUsers(); 

    while(true) { 
     ServerSocket serverSocket = null; 

      inputStream = null ; 
      objectInputStream = null ; 
      outputStream = null ; 
      objectOutputStream = null ; 

     try { 
      serverSocket = new ServerSocket(4444); 
     } catch (IOException e) { 
      System.err.println("Could not listen on port: 4444."); 
      System.exit(1); 
     } 

     Socket clientSocket = null; 
     try { 
      clientSocket = serverSocket.accept(); 
     } catch (IOException e) { 
      System.err.println("Accept failed."); 
      System.exit(1); 
     } 

     PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); 
     BufferedReader in = new BufferedReader(
       new InputStreamReader(
       clientSocket.getInputStream())); 

     inputStream = clientSocket.getInputStream(); 
     objectInputStream = new ObjectInputStream(inputStream); 

     outputStream = clientSocket.getOutputStream(); 
     objectOutputStream = new ObjectOutputStream(outputStream); 
     inputLine = in.readLine(); 

     String inputLine; 
if (inputLine.equals("SAVE PETRI NET START")) { 

      String petriName; 
      String username; 
      String xml ; 
      String input; 
      int result; 
      int size ; 

      petriName = in.readLine(); //read petri name 

      System.out.println("(Server): prijali sme poziadavok na ulozenie " + petriName); 


      username = in.readLine(); //read username 
      System.out.println("(Server): poziadavok ide od usera: " + username); 

      while(true) { 

//this is the line where is occasionally freezes 
       xml = (String)objectInputStream.readObject(); //read object over the network 
      if (!xml.isEmpty()) break; 
      } 


      System.out.println("(Server):" + xml); 

      result = kkp.savePetrinet(username, petriName,xml); //save it to the file 
      out.println(result); 

     } 

     out.close(); 
     in.close(); 
     objectInputStream.close(); 
     inputStream.close(); 
     objectOutputStream.close(); 
     outputStream.close(); 
     clientSocket.close(); 
     serverSocket.close(); 


    } 
    } 
} 

是否有人知道CA ñ是問題? 歡呼聲。

+0

客戶端的線程轉儲在凍結時顯示什麼? – nwinkler 2012-03-15 21:09:23

+1

它看起來就像你在兩個不同的上下文中使用套接字的'InputStream' - 一個背景是在'BufferedReader',另一種是直接調用它的',而(真)'客戶端上的循環中。這本質上是危險的 - 我想無論是使用BufferedReader所有的時間或到InputStream中直接調用所有的時間,但它們混合(各保持自己的狀態,如果你要的InputStream直接調用其內部干擾的BufferedReader可能被打破州)。如果不是在循環中調用InputStream,而是從BufferedReader中讀取數據,會發生什麼? – CodeBlind 2012-03-15 21:10:11

+0

nwinkler - 自卸是空的,沒有輸出,本Lawry - 林不知道如果我得到你的意思,我沒有在客戶端上的任何一段時間(true)循環,並用BufferedReader類IM不知道如何讀的對象,那客戶端發送,監守沒有「的readObject」方法 – 2012-03-15 21:19:47

回答

1

服務器上的Socket InputStream連接到兩個不同的輸入ObjectInputStreamBufferedReaderInputStreams不打算以這種方式使用,並且這樣做會導致很多問題。 BufferedReaders根據其性質將會比您實際閱讀的數據更多地從InputStream中提取更多數據。如果它們碰巧緩衝組成對象的數據,則隨後嘗試讀取ObjectInputStream以外的對象將被阻止,因爲數據已被刪除。

你需要選擇一個方法或其他讀取數據。如果您需要能夠從套接字讀取字符串和對象,那麼您將不得不進入面向字節的操作模式,在該模式下,您將字節讀入字節數組,然後自行處理字節數組,以確保你不會丟失任何數據。基於@Dunes

編輯點評如下

看來最好的辦法是與ObjectInputStream完全堅持並利用它的其他方法,讓您從流中讀取任意的基本類型。而且,如果您不介意已棄用的通話,它甚至有一個readLine方法。

+1

對象輸入/輸出流,因爲它們實現的DataInput/DataOuput以及高度靈活的(讓你發送任何數據類型,你想要的),所以Podvedz應該只是堅持使用對象輸入/輸出而不是試圖像你所建議的那樣做任何事情。 – Dunes 2012-03-15 21:40:11

+0

所以,我已經決定,我將只使用對象輸入(輸出)流,因爲他們是最好的解決方案,我想,但我將不得不重寫一些方法,因爲int是不是對象,但幸運的是,Integer是它:)好像它的工作到目前爲止 – 2012-03-15 21:45:41

+0

@PovedzHeslo,不需要重寫使用'Integer'對象的方法。 'ObjectOutputStream'有一個'writeInt()'方法! (與'writeByte()','writeDouble()'等一起) – 2012-03-15 21:49:05