2017-05-24 9 views
0

GUI用のJavaおよびSwingクラスを使用してチャットアプリケーションを実行しています。Java Swing GUIクライアントおよびサーバーチャットアプリケーションTextAreaが更新されない

ChatServerクラスはクライアントからのメッセージを受信するサーバーになり、すべてのクライアントにエコーバックしますが、2つのクライアントのチャットのみを行います。

ChatClientクラスは、両方ともクライアントです。テキスト領域にサーバーから送信されたものを表示します。テキストフィールドのテキストをサーバーに送信します。

ChatClientクラス

package chatclient; 

import java.net.Socket; 
import java.io.BufferedReader; 
import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.InputStreamReader; 

public class ChatClient extends javax.swing.JFrame { 


public ChatClient() { 
    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() { 

    scrollPane = new javax.swing.JScrollPane(); 
    textArea = new javax.swing.JTextArea(); 
    btnConnect = new javax.swing.JButton(); 
    btnDisconnect = new javax.swing.JButton(); 
    lblStatus = new javax.swing.JLabel(); 
    lblShowStatus = new javax.swing.JLabel(); 
    txtInput = new javax.swing.JTextField(); 

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 
    setTitle("Chat Client A"); 

    textArea.setEditable(false); 
    textArea.setColumns(20); 
    textArea.setRows(5); 
    textArea.setText("Welcome to the Chat Server. Type '/close' or Click 'Disconnect' to close."); 
    textArea.setWrapStyleWord(true); 
    textArea.setCaretPosition(textArea.getDocument().getLength()); 
    scrollPane.setViewportView(textArea); 

    btnConnect.setText("Connect"); 
    btnConnect.setActionCommand("btnConnect"); 
    btnConnect.addMouseListener(new java.awt.event.MouseAdapter() { 
     public void mouseClicked(java.awt.event.MouseEvent evt) { 
      btnConnectMouseClicked(evt); 
     } 
    }); 

    btnDisconnect.setText("Disconnect"); 
    btnDisconnect.setActionCommand("btnDisconnect"); 
    btnDisconnect.addActionListener(new java.awt.event.ActionListener() { 
     public void actionPerformed(java.awt.event.ActionEvent evt) { 
      btnDisconnectActionPerformed(evt); 
     } 
    }); 

    lblStatus.setText("Status: "); 

    lblShowStatus.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N 
    lblShowStatus.setForeground(new java.awt.Color(255, 51, 51)); 
    lblShowStatus.setText("Disconnected"); 

    txtInput.setToolTipText(""); 
    txtInput.addActionListener(new java.awt.event.ActionListener() { 
     public void actionPerformed(java.awt.event.ActionEvent evt) { 
      txtInputActionPerformed(evt); 
     } 
    }); 

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); 
    getContentPane().setLayout(layout); 
    layout.setHorizontalGroup(
     layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
     .addGroup(layout.createSequentialGroup() 
      .addContainerGap() 
      .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
       .addComponent(scrollPane) 
       .addGroup(layout.createSequentialGroup() 
        .addComponent(btnConnect) 
        .addGap(18, 18, 18) 
        .addComponent(btnDisconnect) 
        .addGap(42, 42, 42) 
        .addComponent(lblStatus) 
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 
        .addComponent(lblShowStatus) 
        .addGap(0, 42, Short.MAX_VALUE)) 
       .addComponent(txtInput)) 
      .addContainerGap()) 
    ); 
    layout.setVerticalGroup(
     layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
     .addGroup(layout.createSequentialGroup() 
      .addContainerGap() 
      .addComponent(scrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 213, javax.swing.GroupLayout.PREFERRED_SIZE) 
      .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 11, Short.MAX_VALUE) 
      .addComponent(txtInput, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 
      .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) 
      .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 
       .addComponent(btnConnect) 
       .addComponent(btnDisconnect) 
       .addComponent(lblStatus) 
       .addComponent(lblShowStatus)) 
      .addContainerGap()) 
    ); 

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

private void btnConnectMouseClicked(java.awt.event.MouseEvent evt) {           
    // TODO add your handling code here: 
    lblShowStatus.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N 
    lblShowStatus.setForeground(new java.awt.Color(0, 204, 51)); 
    lblShowStatus.setText("Connected"); 

    // ADD CODES FOR CONNECTING TO CHAT SERVER 

}          

private void btnDisconnectActionPerformed(java.awt.event.ActionEvent evt) {            
    // TODO add your handling code here: 
    lblShowStatus.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N 
    lblShowStatus.setForeground(new java.awt.Color(255, 51, 51)); 
    lblShowStatus.setText("Disconnected"); 

    // ADD CODES FOR DISCONNECTING FROM CHAT SERVER 

}            

private void txtInputActionPerformed(java.awt.event.ActionEvent evt) {           
    // TODO add your handling code here: 
}           

/** 
* @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(ChatClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
    } catch (InstantiationException ex) { 
     java.util.logging.Logger.getLogger(ChatClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
    } catch (IllegalAccessException ex) { 
     java.util.logging.Logger.getLogger(ChatClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
    } catch (javax.swing.UnsupportedLookAndFeelException ex) { 
     java.util.logging.Logger.getLogger(ChatClient.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 ChatClient().setVisible(true); 
     } 
    }); 

    String input = "", serverInput = ""; 
    String host = "localhost"; 
    int port = 1337; 
    Socket client; 

    // updateTextArea("TEST UPDATE"); 

    try { 
     client = new Socket(host, port); 
     System.out.println("Connected to Server!"); 

     DataInputStream in = new DataInputStream(client.getInputStream()); 
     DataOutputStream out = new DataOutputStream(client.getOutputStream()); 

     System.out.println("Before setting text area"); 
     updateTextArea("trying to update"); 

     do { 
      // HANDLE INPUT PART HERE 
      serverInput = in.readUTF(); 


      if(serverInput != null) { 
       System.out.println("Reached here"); 
       System.out.println(serverInput); 
       updateTextArea(serverInput); 
      } 

     } while(!input.equals("/close")); 
     System.out.println("Program closed"); 
    }  

    catch(Exception exc) { 
     System.err.println(exc.getMessage()); 
    } 


} 

private static void updateTextArea(String temp) { 
    textArea.setText(textArea.getText() + "\n" + temp + "\n"); 
    textArea.setCaretPosition(textArea.getDocument().getLength()); 
} 

// Variables declaration - do not modify      
private javax.swing.JButton btnConnect; 
private javax.swing.JButton btnDisconnect; 
private javax.swing.JLabel lblShowStatus; 
private javax.swing.JLabel lblStatus; 
private javax.swing.JScrollPane scrollPane; 
private static javax.swing.JTextArea textArea; 
private javax.swing.JTextField txtInput; 
// End of variables declaration     
} 

ChatServerクラス

package chatserver; 

import java.io.BufferedReader; 
import java.io.InputStreamReader; 
// for testing 
import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.net.ServerSocket; 
import java.net.Socket; 

/** 
* 
* @author wacats 
*/ 
public class ChatServer { 
public static void main(String args[]) { 
    int port = 1337; 

    try { 
     ServerSocket server = new ServerSocket(port); 
     String inMessage = ""; 

     while(true) { 
      Socket clientA = server.accept(); 
      DataInputStream inA = new DataInputStream(clientA.getInputStream()); 
      DataOutputStream outA = new DataOutputStream(clientA.getOutputStream()); 
      // outA.writeUTF("Welcome to the Chat Server. Type '/close' or Click 'Disconnect' to close."); 

      // for testing 
      // BufferedReader user = new BufferedReader(new InputStreamReader(System.in)); 

      do { 
       inMessage = inA.readUTF(); 

       outA.writeUTF("testing"); 

       if(inMessage != null) { 
        outA.writeUTF(inMessage); 
       } 

      } while(!inMessage.equals("/close")); 
      clientA.close(); 
     } 



    } 

    catch(Exception ex) { 
     ex.printStackTrace(); 
    } 
} 
} 

このプログラムのプロセスに関する私の考えは次のとおりです。

  1. 起動ChatServer
  2. チャットクライアントの起動
  3. 両方のクライアントがサーバーに接続されている場合、チャットを開始できます。
  4. 「Enter」を押すと、テキストフィールドのテキストがサーバーに送信されます。
  5. サーバーは両方のクライアントにテキストをブロードキャストします。
  6. クライアントは、サーバーから受信したテキストを追加してテキスト領域を更新します。あなたがしようとupdateTextAreaを呼び出すとき
+1

含めて、上に追いつくために読んだのがたくさんあります。メソッドSwingUtilities.invokeLaterによってラップされたメソッドupdateTextAreaの呼び出しを行う必要があるでしょう。 –

+0

'static '参照を無効にします。 'setText'の上に' append'を使用してください – MadProgrammer

+0

あなたは 'updateTextArea'に' NullPointerException'を持っています。UIが確立される前にサーバからの内容を読み書きするためのループが実行されているためです。 – MadProgrammer

答えて

1

基本的な問題があり、textAreaこれはinvokeLaterコールがまだ実行され、あなたのUIを構築していないので、あなたは基本的には競合状態を持っている、nullです。

スイングでSocket秒に対処するための通常の方法は、SwingWorker

を使用することです詳細はConcurrency in SwingWorker Threads and SwingWorkerを見てください。

問題を解決する方法はいくつかあります。 SwingWorkerを使用すると、ソケットからテキストを読み込み、更新通知(publish/process)メソッドを生成することができます。これは一般に「オブザーバーパターン」として知られています。これは、コードを分離し、より再利用可能なソリューションを生成するので効果的です。あるん

SocketReader

すべてこのクラスはSocketからテキストを読み込んで、単純なテキストからActionEvent Sを生成します。

public class SocketReader extends SwingWorker<Void, String> { 

    private List<ActionListener> actionListeners; 

    public SocketReader() { 
     actionListeners = new ArrayList<>(25); 
    } 

    public void addActionListener(ActionListener listener) { 
     actionListeners.add(listener); 
    } 

    public void removeActionListener(ActionListener listener) { 
     actionListeners.remove(listener); 
    } 

    @Override 
    protected Void doInBackground() throws Exception { 
     System.out.println("Connected to Server!"); 

     try (DataInputStream in = new DataInputStream(SocketManager.INSTACNE.getInputStream())) { 

      System.out.println("Before setting text area"); 

      String serverInput = null; 
      do { 
       // HANDLE INPUT PART HERE 
       serverInput = in.readUTF(); 

       if (serverInput != null) { 
        System.out.println("Read " + serverInput); 
        publish(serverInput); 
       } 

      } while (!serverInput.equals("/close")); 
      System.out.println("Program closed"); 
     } 
     return null; 
    } 

    @Override 
    protected void process(List<String> chunks) { 
     for (String text : chunks) { 
      ActionEvent evt = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, text); 
      for (ActionListener listener : actionListeners) { 
       listener.actionPerformed(evt); 
      } 
     } 
    } 

} 

SocketWriter

シンプルSocketにこの簡単な書き込みテキスト、

。技術的には、さて、これは私の一部にやや過剰ですが、私はしたいあなたは、このために SwingWorkerを使用する必要はありませんが、私はそれが

public class SocketWriter extends SwingWorker<Void, Void> { 

    private List<String> messages; 
    private ReentrantLock lock; 
    private Condition waitCon; 

    public SocketWriter() { 
     messages = Collections.synchronizedList(new ArrayList<String>(25)); 
     lock = new ReentrantLock(); 
     waitCon = lock.newCondition(); 
    } 

    public void write(String text) { 
     System.out.println("Write " + text); 
     messages.add(text); 
     try { 
      lock.lock(); 
      waitCon.signalAll(); 
     } finally { 
      lock.unlock(); 
     } 
    } 

    @Override 
    protected Void doInBackground() throws Exception { 
     try (DataOutputStream out = new DataOutputStream(SocketManager.INSTACNE.getOutputStream())) { 
      while (!isCancelled()) { 
       while (messages.isEmpty() && !isCancelled()) { 
        try { 
         lock.lock(); 
         waitCon.await(); 
        } finally { 
         lock.unlock(); 
        } 
       } 
       List<String> cache = new ArrayList<>(messages); 
       messages.clear(); 
       for (String text : cache) { 
        System.out.println("Send " + text); 
        out.writeUTF(text); 
       } 
      } 
     } 
     return null; 
    } 

} 

SocketManager

をキャンセルすることは比較的簡単だという事実が好きSocketの中央コントローラでシングルトンを使用する必要はありません。シンプルなクラスにして、その参照をChatClientに渡してSocketReader/Writerに渡すこともできますが、遅くて怠け者です

public enum SocketManager { 
    INSTACNE; 

    private String host = "localhost"; 
    private int port = 1337; 
    private Socket socket; 

    public Socket open() throws IOException { 
     if (socket != null) { 
      close(); 
     } 
     socket = new Socket(host, port); 
     return socket; 
    } 

    public void close() throws IOException { 
     if (socket == null) { 
      return; 
     } 
     socket.close(); 
    } 

    public boolean isOpen() { 
     return socket != null 
      && socket.isConnected() 
      && !socket.isClosed() 
      && !socket.isInputShutdown() 
      && !socket.isOutputShutdown(); 
    } 

    public InputStream getInputStream() throws IOException { 
     Objects.requireNonNull(socket, "Socket is not open"); 
     return socket.getInputStream(); 
    } 

    public OutputStream getOutputStream() throws IOException { 
     Objects.requireNonNull(socket, "Socket is not open"); 
     return socket.getOutputStream(); 
    } 
} 

ChatClient

これはすごく素晴らしいものですが、どのように使用すると思いますか?

ウィルは、非常に基本的に、あなたはChatClientSocketReaderSocketWriterのインスタンスを作成し、あなたがリーダーにActionListenerを添付し、それが引き金だときJTextAreaを更新し、例えば、SocketWriterに送信されたテキストを送ります... 。

public class ChatClient extends javax.swing.JFrame { 

    public ChatClient() { 
     initComponents(); 
     socketReader = new SocketReader(); 
     socketReader.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       String text = e.getActionCommand(); 
       textArea.append(text); 
       textArea.append("\n"); 
       textArea.setCaretPosition(textArea.getDocument().getLength()); 
      } 
     }); 
     socketReader.execute(); 

     socketWriter = new SocketWriter(); 
     socketWriter.execute(); 
    } 

    /** 
    * 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() { 

     scrollPane = new javax.swing.JScrollPane(); 
     textArea = new javax.swing.JTextArea(); 
     btnConnect = new javax.swing.JButton(); 
     btnDisconnect = new javax.swing.JButton(); 
     lblStatus = new javax.swing.JLabel(); 
     lblShowStatus = new javax.swing.JLabel(); 
     txtInput = new javax.swing.JTextField(); 

     setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 
     setTitle("Chat Client A"); 

     textArea.setEditable(false); 
     textArea.setColumns(20); 
     textArea.setRows(5); 
     textArea.setText("Welcome to the Chat Server. Type '/close' or Click 'Disconnect' to close."); 
     textArea.setWrapStyleWord(true); 
     textArea.setCaretPosition(textArea.getDocument().getLength()); 
     scrollPane.setViewportView(textArea); 

     btnConnect.setText("Connect"); 
     btnConnect.setActionCommand("btnConnect"); 
     btnConnect.addMouseListener(new java.awt.event.MouseAdapter() { 
      public void mouseClicked(java.awt.event.MouseEvent evt) { 
       btnConnectMouseClicked(evt); 
      } 
     }); 

     btnDisconnect.setText("Disconnect"); 
     btnDisconnect.setActionCommand("btnDisconnect"); 
     btnDisconnect.addActionListener(new java.awt.event.ActionListener() { 
      public void actionPerformed(java.awt.event.ActionEvent evt) { 
       btnDisconnectActionPerformed(evt); 
      } 
     }); 

     lblStatus.setText("Status: "); 

     lblShowStatus.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N 
     lblShowStatus.setForeground(new java.awt.Color(255, 51, 51)); 
     lblShowStatus.setText("Disconnected"); 

     txtInput.setToolTipText(""); 
     txtInput.addActionListener(new java.awt.event.ActionListener() { 
      public void actionPerformed(java.awt.event.ActionEvent evt) { 
       txtInputActionPerformed(evt); 
      } 
     }); 

     javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); 
     getContentPane().setLayout(layout); 
     layout.setHorizontalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGroup(layout.createSequentialGroup() 
       .addContainerGap() 
       .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
        .addComponent(scrollPane) 
        .addGroup(layout.createSequentialGroup() 
         .addComponent(btnConnect) 
         .addGap(18, 18, 18) 
         .addComponent(btnDisconnect) 
         .addGap(42, 42, 42) 
         .addComponent(lblStatus) 
         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 
         .addComponent(lblShowStatus) 
         .addGap(0, 42, Short.MAX_VALUE)) 
        .addComponent(txtInput)) 
       .addContainerGap()) 
     ); 
     layout.setVerticalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGroup(layout.createSequentialGroup() 
       .addContainerGap() 
       .addComponent(scrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 213, javax.swing.GroupLayout.PREFERRED_SIZE) 
       .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 11, Short.MAX_VALUE) 
       .addComponent(txtInput, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 
       .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) 
       .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 
        .addComponent(btnConnect) 
        .addComponent(btnDisconnect) 
        .addComponent(lblStatus) 
        .addComponent(lblShowStatus)) 
       .addContainerGap()) 
     ); 

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

    private void btnConnectMouseClicked(java.awt.event.MouseEvent evt) { 
     // TODO add your handling code here: 
     lblShowStatus.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N 
     lblShowStatus.setForeground(new java.awt.Color(0, 204, 51)); 
     lblShowStatus.setText("Connected"); 

     // ADD CODES FOR CONNECTING TO CHAT SERVER 
    } 

    private void btnDisconnectActionPerformed(java.awt.event.ActionEvent evt) { 
     // TODO add your handling code here: 
     lblShowStatus.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N 
     lblShowStatus.setForeground(new java.awt.Color(255, 51, 51)); 
     lblShowStatus.setText("Disconnected"); 

     // ADD CODES FOR DISCONNECTING FROM CHAT SERVER 
    } 

    private void txtInputActionPerformed(java.awt.event.ActionEvent evt) { 
     if (SocketManager.INSTACNE.isOpen()) { 
      socketWriter.write(txtInput.getText()); 
     } else { 
      System.out.println("!! Not open"); 
     } 
    } 

    /** 
    * @param args the command line arguments 
    */ 
    public static void main(String args[]) { 

     try { 
      /* 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(ChatClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
      } catch (InstantiationException ex) { 
       java.util.logging.Logger.getLogger(ChatClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
      } catch (IllegalAccessException ex) { 
       java.util.logging.Logger.getLogger(ChatClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
      } catch (javax.swing.UnsupportedLookAndFeelException ex) { 
       java.util.logging.Logger.getLogger(ChatClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
      } 
      //</editor-fold> 

      SocketManager.INSTACNE.open(); 

      /* Create and display the form */ 
      java.awt.EventQueue.invokeLater(new Runnable() { 
       public void run() { 
        new ChatClient().setVisible(true); 
       } 
      }); 

     } catch (IOException ex) { 
      ex.printStackTrace(); 
     } 
     //</editor-fold>  

    } 

    private SocketWriter socketWriter; 
    private SocketReader socketReader; 

    // Variables declaration - do not modify      
    private javax.swing.JButton btnConnect; 
    private javax.swing.JButton btnDisconnect; 
    private javax.swing.JLabel lblShowStatus; 
    private javax.swing.JLabel lblStatus; 
    private javax.swing.JScrollPane scrollPane; 
    private javax.swing.JTextArea textArea; 
    private javax.swing.JTextField txtInput; 
    // End of variables declaration     
} 

あなたは、私は申し訳ありませんが、あなたがコードを "接続" 逃し、mainSocketManager#openを使用、注意しましょう。ときに私は、これまでの変更の多くを作るが、念のため...

public class ChatServer { 

    public static void main(String args[]) { 
     int port = 1337; 

     try { 
      ServerSocket server = new ServerSocket(port); 
      String inMessage = ""; 

      while (true) { 
       System.out.println("Waiting"); 
       Socket clientA = server.accept(); 
       System.out.println("Connected"); 
       DataInputStream inA = new DataInputStream(clientA.getInputStream()); 
       DataOutputStream outA = new DataOutputStream(clientA.getOutputStream()); 
       // outA.writeUTF("Welcome to the Chat Server. Type '/close' or Click 'Disconnect' to close."); 

       // for testing 
       // BufferedReader user = new BufferedReader(new InputStreamReader(System.in)); 
       do { 
        inMessage = inA.readUTF(); 

        if (inMessage != null) { 
         outA.writeUTF(inMessage); 
        } 

       } while (!inMessage.equals("/close")); 
       clientA.close(); 
      } 

     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 
} 

通常はしませんでした

ChatServer

);私が代わりにそのメソッドにいることを示唆している移動しますクライアントが接続すると、新しいThreadを開始し、クライアントSocketを処理しますが、それは私の焦点では​​ありませんでした。

だから、すべてのことに基づいて、あなたはあなたがSwingのスレッドでテキストエリアを更新する必要がありConcurrency in JavaAll About Sockets

+0

NetBeansは 'static'キーワードをクラス宣言 – wacats

+0

@wacatsそれから取り出して、テスト中に簡単に1つのファイルにコードを設定しました。削除するのを忘れました:P – MadProgrammer

+0

2つの異なるChatClientクラスを起動すると、代わりに独自の送信メッセージが表示されます互いの間でメッセージを同期させるということは、私がChatClientでのマルチスレッドの実装が間違っているためだと思っていました。ここで質問をフォローアップするhttps://stackoverflow.com/questions/44163293/making-a-new-thread-in-java-swing-gui-chat-app – wacats

関連する問題