1

このコードについて助けが必要です。クライアントからクライアントにメッセージをエコーバックし、クライアントが「BYE」と入力した後に閉じることを想定しているサーバーに関するものです。ただし、メッセージはサーバーが閉じられた後にのみクライアントに表示されます。

この問題の解決策を得ることができれば、私は感謝します

これはサーバー側のコードです:

import java.io.*;
import java.net.*; 
import java.util.*;
import java.awt.*;
import javax.swing.*;

public class EchoServer extends JFrame{

   private JTextArea jta = new JTextArea();

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

public EchoServer(){

   setLayout(new BorderLayout());
   add(new JScrollPane(jta), BorderLayout.CENTER);

   setTitle("Server");
   setSize(500, 300);
   setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   setVisible(true);

   try {

     //Creating Server socket  

     ServerSocket s = new ServerSocket(5000);

    //Display messge to show the server has bean running
    jta.append("Echo Server Started" + '\n');
    /*This is a blocking Statement
    *The program comes to a stand still until the ACCEPT method returns
          */

    Socket incoming = s.accept(); 

    jta.append("Connected to: " + incoming.getInetAddress() +
                     " at port: " + incoming.getLocalPort() + '\n' + '\n'); 



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


    //Display welcome message

     out.println("Hi my SERVER. Enter BYE to exit."); 


     for (;;) {
       String str = in.readLine(); 
       if (str == null) {
         break; 
       } else {

          //Display information from Client  

          out.println("Echo: " + str); 


          jta.append("Received: " + str + '\n');

          if (str.trim().equals("BYE")) 
          break; 
      }
    }
    //incoming.close(); 
  } catch (Exception e) {
     jta.append("Error: " + e); 
    }

    jta.append("EchoServer stopped."); 
  }

}

そして、これはクライアント側のコードです:

import java.io.*;
import java.net.*; 
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;


public class Client extends JFrame {

private JTextField jtf = new JTextField();

private JTextArea jta = new JTextArea();

private BufferedReader in;
private PrintWriter out;

public static void main(String[] args){

    new Client();
}

public Client(){

    JPanel p = new JPanel();
    p.setLayout(new BorderLayout());
    p.add(new JLabel("Enter Text:"), BorderLayout.WEST);
    p.add(jtf, BorderLayout.CENTER);
    jtf.setHorizontalAlignment(JTextField.RIGHT);

    setLayout(new BorderLayout());
    add(p, BorderLayout.NORTH);
    add(new JScrollPane(jta), BorderLayout.CENTER);

    jtf.addActionListener(new TextFieldListener());

    setTitle("Client");
    setSize(500, 300);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);

    try {

        //creating a socket

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


        in = new 
            BufferedReader(new InputStreamReader(socket.getInputStream()));

        out = new 
            PrintWriter(socket.getOutputStream(), true);

    }
    catch(IOException ex){
        jta.append(ex.toString() + '\n');
    }
}

private class TextFieldListener implements ActionListener {
    @Override

    public void actionPerformed(ActionEvent e){
       try{
          while (true){                

                String str= in.readLine();

                if (str == null) {

                    //break out of loop

                    break;
                } else {

                    //Display input from server
                    jta.append(str  + "\n");


                    /*enable user to in the text that 
                        will be sent ot the server
                    */
                    String sms = jtf.getText().trim();

                    if ("BYE".equals(sms)){

                        /*if the user types "BYE" send it to the server
                            and break out of the loop
                        */

                        out.println("BYE");

                        break;
                    }

                    //send messages to the server
                    out.println("line " + sms);

                } 
          }
       }
       catch (IOException ex) {
           System.err.println(ex);
       }
    }
  }
}
4

1 に答える 1

4

Swing スレッドの問題があります。Swingwhile (true)イベント スレッドがブロックされており、プログラムがフリーズしています。この問題を回避できるように、バックグラウンド スレッド、特に SwingWorker スレッドの使用についてお読みください。Swing チュートリアルでの同時実行から始めます。

また、ユーザーが何かを入力した後にのみ読み取りを開始し、同じ文字列をサーバーに何度も送信しています。

私は提案します:

  • バックグラウンド スレッドまたは SwingWorker を使用して、クライアントでサーバーから読み取ります。これは、ActionListener ではなく、クライアントのコンストラクターで設定する必要があります。
  • Swing イベント スレッドまたは EDTのクライアントのテキスト領域必ず追加してください。SwingWorker は、publish/process メソッドのペアを介してこれを行うのに役立ちます。
  • ActionListener ははるかに単純なはずです。JTextField のテキストを取得し、それをout経由でフィールドに送信するだけout.println(...)です。
  • 繰り返しますが、同じ文字列をサーバーに何度も何度も送信する場合を除いてout.println("line " + sms);、ループの中に入れないでください。while (true)繰り返しますが、これは ActionListener 内にある必要があり、ループ内で呼び出されるのではなく、リスナーが実行されたときにのみ呼び出されるワンショット ディールである必要があります。

たとえば、ActionListener は次のように単純にすることができます。

private class TextFieldListener implements ActionListener {
  @Override
  public void actionPerformed(ActionEvent e) {
     String sms = jtf.getText().trim();
     out.println("line " + sms);
  }
}

そして Client コンストラクターで:

  try {
     Socket socket = new Socket("localhost", 5000);
     in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

     // !!
     new Thread(new Runnable() {

        @Override
        public void run() {
           try {
              while (true) {
                 final String str = in.readLine();
                 if (str == null) {
                    break;
                 } else {

                    // ***** call Swing code on the Swing event thread:
                    SwingUtilities.invokeLater(new Runnable() {
                       public void run() {
                          jta.append(str + "\n");
                       }
                    });

                    // String sms = jtf.getText().trim();
                    // if ("BYE".equals(sms)) {
                    //    out.println("BYE");
                    //    break;
                    // }
                    // ***** don't call this here!!! *****
                    // out.println("line " + sms);
                 }
              }
           } catch (IOException ex) {
              System.err.println(ex);
           }
        }
     }).start();

     out = new PrintWriter(socket.getOutputStream(), true);
  } catch (IOException ex) {
     jta.append(ex.toString() + '\n');
  }
于 2013-10-23T21:47:09.650 に答える