2012-03-15 8 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何を知っていますサーバーのコードですn問題? 歓声。

+0

クライアントのスレッドダンプは、凍結時にどのように表示されますか? – nwinkler

+1

ソケットの 'InputStream'を2つの異なるコンテキストで使用しているようです.1つのコンテキストは' BufferedReader'にあり、もう1つはクライアントの 'while(true)'ループの中で直接呼び出しています。これは本質的に危険です - 私はいつもBufferedReaderを使用するか、InputStreamへの直接呼び出しを常に行っていますが、それらをミックスします(それぞれは独自の状態を維持し、InputStreamへの直接呼び出しが内部状態)。ループ内でInputStreamを呼び出す代わりに、代わりにBufferedReaderから読み込むとどうなりますか? – CodeBlind

+0

nwinkler - dumpは空ですが、出力はありません。Ben Lawry - あなたが何を意味しているのかわかりません。クライアント上で(真の)ループがなく、BufferedReaderでオブジェクトを読み込む方法がわかりません。クライアントの場合は、 "readObject"メソッドがないため、 –

答えて

1

2つの異なる入力に接続されたサーバー上のソケット入力ストリームは、とBufferedReaderです。 InputStreamsはこの方法で使用することは意図されていません。そうすることで多くの問題が発生する可能性があります。 BufferedReadersはその性質上、実際に読んでいるよりも多くのデータをInputStreamから引き出します。オブジェクトを構成するデータをバッファリングすると、データがすでに削除されているため、後でオブジェクトをObjectInputStreamから読み取ろうとするとブロックされます。

データを読み取るには、どちらか一方の方法を選択する必要があります。文字列とオブジェクトの両方をSocketから読み取る必要がある場合は、バイト指向の操作モードに進んで、バイトをバイト配列に読み込んだ後、バイト配列を自分自身で処理してデータを失うことはありません。

以下@Dunesのコメントに基づいて

編集はあなたの最善の策は、ObjectInputStreamで完全に固執し、あなたは、ストリームから任意のプリミティブ型を読み取ることができ、そのほかの方法を活用することであるようです。また、非推奨の呼び出しに気にしない場合は、readLineメソッドもあります。

+1

オブジェクト入出力ストリームは、DataInput/DataOuputも実装しています(必要なデータ型を送信できるようになります)ので、Podvedzはオブジェクトの入出力あなたが提案したように何かをやろうとするのではなく、ストリームにすることができます。 – Dunes

+0

したがって、私はオブジェクト入力ではないので、私はいくつかのメソッドを書き直す必要がありますが、私は思う最良のソリューションであるため、オブジェクト入力(出力)ストリームのみを使用することに決めました。これまでの作業のように思えます。 –

+0

@PovedzHeslo、 'Integer'オブジェクトを使うメソッドを書き直す必要はありません。 'ObjectOutputStream'は' writeInt() 'メソッドを持っています! ( 'writeByte()'、 'writeDouble()'などと一緒に) –

関連する問題