2012-03-23 4 views
0

私はjavaで新しく、TCPソケットを使用して単純なクライアントサーバーを作成しようとしましたが、数日間苦労してこの問題を解決できませんでした。JavaソケットBufferReader.readline get null

私はBufferReader.Readline()でnullを取得しました。

MYサーバコード:

スタートServerコード

public class StartServer { 
    ServerSocket server; 
    public StartServer(){ 
     try { 
      server = new ServerSocket(4444); 
     } catch (Exception e) { 
      System.out.println("server can't listen to this port"); 
     } 
     System.out.println("Listening for clients on 4444..."); 
     int id =0; 
     while(true) 
     { 
      try { 
       Socket client = server.accept(); 
       ServerThread svThread = new ServerThread(client, id++); 
       svThread.start(); 
      } catch (Exception e) { 
       System.out.println("Error......."); 
      } 
     } 
    } 

    public static void main(String[] args) { 
     new StartServer(); 
    } 

} 

サーバーのスレッド:

public class ServerThread extends Thread{ 
    Socket client; 
    int clientID = 0; 
    boolean threadRun = true; 
    BufferedReader inputFromClient = null; 
    PrintWriter outputFromServer = null; 

    public ServerThread(Socket socket, int cID) { 
     client = socket; 
     clientID = cID; 
    } 


    public void run() { 
     try { 
      inputFromClient = new BufferedReader(new InputStreamReader(client.getInputStream())); 
      outputFromServer = new PrintWriter(new OutputStreamWriter(client.getOutputStream())); 
      System.out.println("ClientID: " + clientID); 

      while(threadRun){ 
       String textFromClient = inputFromClient.readLine(); 
       System.out.println("Client ID: " + clientID + " Client says: " + textFromClient); 

       if(textFromClient.equals("Quit")){ 
        threadRun = false; 
        System.out.println("Stop client Thread from: " + clientID); 
       }else{ 
        outputFromServer.print(textFromClient); 
        outputFromServer.flush(); 
       } 
      } 
     } catch (IOException ex) { 
      Logger.getLogger(ServerThread.class.getName()).log(Level.SEVERE, null, ex); 
     }finally{ 
      try { 
       inputFromClient.close(); 
       outputFromServer.close(); 
       client.close(); 
       System.out.println("Server Stopped..."); 
      } catch (Exception e) { 
      } 
     } 
    } 




} 

私のクライアント私はJFrameのは、パネルを呼び出し、にメッセージを送信するには、テキストフィールドとのJButtonを使用して使用しますサーバー

しかし、1つのメッセージを送信すると、サーバーはこのメッセージを受信できます

のJFrameコード:Eとコマンドラインにそれをプリントアウトが、それは(その中にwhileループので)クライアントからメッセージを取得しようと続けるが、それがnullを受け、私はこのような状況で

私のクライアントコードを見当がつかない:

public class NewJFrame extends javax.swing.JFrame { 

    /** 
    * Creates new form NewJFrame 
    */ 

    Panel1 p ; 
    public NewJFrame() { 
     initComponents(); 
    } 

    /** 
    * This method is called from within the constructor to initialize the form. 
    * WARNING: Do NOT modify this code. The content of this method is always 
    * regenerated by the Form Editor. 
    */ 
    @SuppressWarnings("unchecked") 
    // <editor-fold defaultstate="collapsed" desc="Generated Code">       
    private void initComponents() { 

     jDesktopPane1 = new javax.swing.JDesktopPane(); 
     jPanel1 = new javax.swing.JPanel(); 
     jButton1 = new javax.swing.JButton(); 

     setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 

     jButton1.setText("jButton1"); 
     jButton1.addActionListener(new java.awt.event.ActionListener() { 
      public void actionPerformed(java.awt.event.ActionEvent evt) { 
       jButton1ActionPerformed(evt); 
      } 
     }); 

     javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); 
     jPanel1.setLayout(jPanel1Layout); 
     jPanel1Layout.setHorizontalGroup(
      jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() 
       .addContainerGap(196, Short.MAX_VALUE) 
       .addComponent(jButton1) 
       .addGap(91, 91, 91)) 
     ); 
     jPanel1Layout.setVerticalGroup(
      jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGroup(jPanel1Layout.createSequentialGroup() 
       .addGap(83, 83, 83) 
       .addComponent(jButton1) 
       .addContainerGap(134, Short.MAX_VALUE)) 
     ); 

     jPanel1.setBounds(0, 0, 360, 240); 
     jDesktopPane1.add(jPanel1, javax.swing.JLayeredPane.DEFAULT_LAYER); 

     javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); 
     getContentPane().setLayout(layout); 
     layout.setHorizontalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGroup(layout.createSequentialGroup() 
       .addComponent(jDesktopPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 365, javax.swing.GroupLayout.PREFERRED_SIZE) 
       .addGap(0, 35, Short.MAX_VALUE)) 
     ); 
     layout.setVerticalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGroup(layout.createSequentialGroup() 
       .addComponent(jDesktopPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 265, javax.swing.GroupLayout.PREFERRED_SIZE) 
       .addGap(0, 35, Short.MAX_VALUE)) 
     ); 

     pack(); 
    }// </editor-fold>       

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {           
     // TODO add your handling code here: 
     p = new Panel1(); 
     jDesktopPane1.removeAll(); 
     jDesktopPane1.repaint(); 
     jDesktopPane1.revalidate(); 
     p.setBounds(0, 0, 840, 558); 
     p.setSize(840,558); 
     jDesktopPane1.add(p); 
     p.show(); 

    }           

    /** 
    * @param args the command line arguments 
    */ 
    public static void main(String args[]) { 
     /* 
     * Set the Nimbus look and feel 
     */ 
     //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) "> 
     /* 
     * If Nimbus (introduced in Java SE 6) is not available, stay with the 
     * default look and feel. For details see 
     * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
     */ 
     try { 
      for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { 
       if ("Nimbus".equals(info.getName())) { 
        javax.swing.UIManager.setLookAndFeel(info.getClassName()); 
        break; 
       } 
      } 
     } catch (ClassNotFoundException ex) { 
      java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } catch (InstantiationException ex) { 
      java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } catch (IllegalAccessException ex) { 
      java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } catch (javax.swing.UnsupportedLookAndFeelException ex) { 
      java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } 
     //</editor-fold> 

     /* 
     * Create and display the form 
     */ 
     java.awt.EventQueue.invokeLater(new Runnable() { 

      public void run() { 
       new NewJFrame().setVisible(true); 
      } 
     }); 
    } 
    // Variables declaration - do not modify      
    private javax.swing.JButton jButton1; 
    private javax.swing.JDesktopPane jDesktopPane1; 
    private javax.swing.JPanel jPanel1; 
    // End of variables declaration     
} 

Myパネルコード:

public class Panel1 extends javax.swing.JPanel { 
Socket s; 
PrintWriter outPut = null; 
    /** 
    * Creates new form Panel1 
    */ 
    public Panel1() { 
     initComponents(); 
     ConnectServer(); 
     //sendToServer(); 
     // receiveFromServer(); 
    } 

    /** 
    * This method is called from within the constructor to initialize the form. 
    * WARNING: Do NOT modify this code. The content of this method is always 
    * regenerated by the Form Editor. 
    */ 

    public void ConnectServer(){ 
     try { 
      s = new Socket("localhost", 4444); 
      System.out.println("Connect to server"); 
      outPut = new PrintWriter(new OutputStreamWriter(s.getOutputStream())); 
      // PrintWriter outPut = new PrintWriter(new OutputStreamWriter(s.getOutputStream())); 
      //outPut.println("Test cai coi....."); 
      //outPut.flush(); 
     } catch (UnknownHostException ex) { 
      Logger.getLogger(Panel1.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (IOException ex) { 
      Logger.getLogger(Panel1.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 

    public void receiveFromServer(){ 
     try { 
      BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream())); 
      System.out.println(input.readLine()); 
     } catch (IOException ex) { 
      Logger.getLogger(Panel1.class.getName()).log(Level.SEVERE, null, ex); 
     } 

    } 


    @SuppressWarnings("unchecked") 
    // <editor-fold defaultstate="collapsed" desc="Generated Code">       
    private void initComponents() { 

     jTextField1 = new javax.swing.JTextField(); 
     jButton1 = new javax.swing.JButton(); 

     jButton1.setText("jButton1"); 
     jButton1.addActionListener(new java.awt.event.ActionListener() { 
      public void actionPerformed(java.awt.event.ActionEvent evt) { 
       jButton1ActionPerformed(evt); 
      } 
     }); 

     javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); 
     this.setLayout(layout); 
     layout.setHorizontalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGroup(layout.createSequentialGroup() 
       .addGap(26, 26, 26) 
       .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, 138, javax.swing.GroupLayout.PREFERRED_SIZE) 
       .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 
       .addComponent(jButton1) 
       .addContainerGap(157, Short.MAX_VALUE)) 
     ); 
     layout.setVerticalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGroup(layout.createSequentialGroup() 
       .addGap(34, 34, 34) 
       .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 
        .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 
        .addComponent(jButton1)) 
       .addContainerGap(243, Short.MAX_VALUE)) 
     ); 
    }// </editor-fold>       

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {           
     //PrintWriter outPut = null; 
     PrintWriter outToServer = null; 
     BufferedReader input = null; 
     try { 
      // TODO add your handling code here: 
      outToServer = new PrintWriter(new OutputStreamWriter(s.getOutputStream())); 

      String txtFromClient = jTextField1.getText(); 
      // String clientText = input.readLine(); 
      System.out.println(txtFromClient); 
      outToServer.println(txtFromClient); 
      outToServer.flush(); 

      // 





      //outPut.flush(); 
      //System.out.println(input.readLine()); 
     } catch (Exception ex) { 
      Logger.getLogger(Panel1.class.getName()).log(Level.SEVERE, null, ex); 
     } finally { 
      //outPut.close(); 
      outToServer.close(); 
     } 


    }           

    // Variables declaration - do not modify      
    private javax.swing.JButton jButton1; 
    private javax.swing.JTextField jTextField1; 
    // End of variables declaration     
} 

し、サーバからの私のスタックトレース:

Exception in thread "Thread-0" java.lang.NullPointerException 
    at testserverclient.ServerThread.run(ServerThread.java:39) 

ライン39は、次のとおりです。

if(textFromClient.equals("Quit")) 

答えて

1

nullを返しBufferedReader.readLine()とき、それは読むためにこれ以上データがありませんを意味します。あなたはストリームの終わりにいます。 nullはオブジェクトではない(一般的に、他端が接続を閉じた状態を意味するソケットを有する。)

もちろん、null.equals(anything)は例外をスローします。

あなたはいずれかの条件が、クライアントが行われ、接続が終了されるべきであることを意味するので

if (textFromClient == null || textFromClient.equals("Quit")) 

のようなものを言うことによって例外を回避することができます。

クライアントとしては、ソケット(あなたがjButton1ActionPerformedで行っているように)によってあなたに与えられたストリームを閉じて、ソケットも閉じます。おそらく、最上位のストリームメンバフィールドをクライアントのどこかに置いて、コールの間にそれらを保持することができます。

2

終了メッセージを処理するという考えは良いです。しかし、あなたのクライアントは決してそのような終了メッセージを送信しません。それは単にソケットを閉じます。これにより、ソケット(サーバー)の反対側で、次の行を要求するときにBufferedReaderがnullを返すことになります。したがって、これを解決するには、クライアントがquit-messageを書き込むようにしてください。これにより、サーバーは適切な時点でソケットを閉じ、そこからの読み取りを停止します。また、返されたStringがnullの場合は、サーバー側のチェックを追加してください。

if (textFromClient == null || textFromClient.equals("Quit")) 
{ 
    socket.close(); 
    break; // Break out of the reading loop. 
} 

編集:そして、クライアント側でこの:

if (txtFromClient.equals("Quit")) 
{ 
    outToServer.println("Quit"); 
    outToServer.flush(); 
    outToServer.close(); 
} 

あなたはfinallyブロックでソケットをクローズしていないことを確認してください。終了メッセージを送信するときにのみ閉じます。


ヒント:あなたは、オートフラッシュモードでのPrintStreamを構築することができます:自動フラッシュを有効にする場合

PrintStream outToServer = new PrintStream(socket.getOutputStream, true); 

、それは各印刷(LN)の文の後にフラッシュします。だから毎回電話する必要はありませんflush()

+0

ありがとう 私はクライアントスレッドが休憩しているときにサーバーに新しいテキストを送信できません。なぜなら、テキストフィールドはサーバーにテキストを送信するので、サーバーに別のテキストを送信したいのですがどうすればいいですか? – Bronx

+0

@Bronx:答えを編集しました。これはうまくいくはずだと思います。 –

+0

あなたの助けを 最初にあなたの助けをありがとうしかし、上記のあなたのソリューションとして、サーバーがヌルを受信すると、クライアントはサーバーに何も送信しないクライアントが切断されますが、私のアプリケーションでは、サーバーは、クライアントのIDを作成し、このIDを他のメソッドに使用したいが、クライアントはサーバーに何もないし、そのサーバーを切断した後、クライアントが再接続すると新しいIDを取得し、クライアントの、それは私のためにひどいだろう、それは新しいIDを得るクライアント:( – Bronx