5

ソケットを使用してJavaクライアント/サーバーGUIアプリケーションを作成していますが、ここに問題があります:

指定したポートのリッスンを開始するボタンがあります。

ボタンアクション実行メソッド

private void listenButtonActionPerformed(java.awt.event.ActionEvent evt) {                                             
    int port = Integer.parseInt(portTextfield.getText(), 10);

    try {
        socket.listen(port);
    } catch (IOException ex) {
    }
}

ここに socket.listen メソッドがあります

public static void listen() throws IOException {
    ServerSocket ss = new ServerSocket(port);

    while (true)
        new socket(ss.accept());
}

「ソケット」クラスは「スレッド」を拡張
するため、ss.accept() が値を返した後、別のスレッドで新しいソケット インスタンスを作成します。

ボタンをクリックすると、socket.listen メソッド内に無限ループがあるため、GUI がフリーズします。どうすればそれを回避できますか?

4

5 に答える 5

5

設計には 2 つの落とし穴があります。

  1. ss.accept()ブロッキング呼び出しであるため、着信接続があるまで UI がフリーズします
  2. while(true)EDT でループを実行しないでください。

代わりに、次のようにします。

  • ボタンがクリックされると、着信接続のリッスンを開始するスレッドを作成します。
  • 着信接続があるときはいつでも、着信クライアント接続を取得して処理する別のスレッドを作成します。
于 2012-06-25T08:36:35.887 に答える
4

これをチェックしてください:http://javarevisited.blogspot.ro/2012/02/what-is-blocking-methods-in-java-and.html

1)GUIアプリケーションを作成している場合は、Swingを使用している可能性があり、イベントディスパッチャスレッドまたはイベントハンドラでブロッキングメソッドを呼び出さないでください。たとえば、ボタンがクリックされたときにファイルを読み取ったり、ネットワーク接続を開いたりしている場合は、actionPerformed()メソッドでそれを行わないでください。代わりに、そのジョブを実行してactionPerformed()から戻るための別のワーカースレッドを作成してください。これによりGUIの応答性が維持されますが、同期更新にinvokeAndWait()を使用することを検討するよりも、操作をユーザーが待機する必要があるかどうかは、設計によって異なります。

複数のスレッドを使用する:http://javarevisited.blogspot.ro/2011/02/how-to-implement-thread-in-java.html

于 2012-06-25T08:08:23.110 に答える
3

マルチスレッドを使用する必要があります。私なら、GUI コードとサーバー コードを分離し、ボタンが押されたときにサーバー コードを新しいスレッドとして起動します。

すべてのイベントがイベント ディスパッチャー スレッド (EDT) で実行されるため、コードは基本的に GUI をフリーズさせます。これは、すべての GUI とそれぞれのイベントを処理するスレッドです。ブロックするか、停止するか、ループをスローすると、パフォーマンスに影響します。

于 2012-06-25T08:03:46.317 に答える
2

これらを試してみてください...

1. During getting the initial connection delay can occur, so first create and empty socket,then try to connect to the server.

   `Socket s = new Socket();`

   `s.connect(new InetSocketAddress("ip_addr",port_nos),1000);`

2. And Secondly always keep the Non-UI work out of Your UI thread..

これが私のサーバーの例です-クライアント通信..

クライアント側のコード:

public class ClientWala {

    public static void main(String[] args) throws Exception{

        Boolean b = true;
    Socket s = new Socket();
    s.connect(new InetSocketAddress("127.0.0.1", 4444),1000);

    System.out.println("connected: "+s.isConnected());


    OutputStream output = s.getOutputStream();
    PrintWriter pw = new PrintWriter(output,true);

    // to write data to server
    while(b){

        if (!b){

             System.exit(0);
        }

        else {
            pw.write(new Scanner(System.in).nextLine());
        }
    }


    // to read data from server
    InputStream input   = s.getInputStream();
    InputStreamReader isr = new InputStreamReader(input);
    BufferedReader br = new BufferedReader(isr);
    String data = null;

    while ((data = br.readLine())!=null){

        // Print it using sysout, or do whatever you want with the incoming data from server

    }




    }
}

サーバー側のコード:

import java.io.*
import java.net.*;


public class ServerTest {

    ServerSocket s;

    public void go() {

        try {
            s = new ServerSocket(44457);

            while (true) {

                Socket incoming = s.accept();
                Thread t = new Thread(new MyCon(incoming));
                t.start();
            }
        } catch (IOException e) {

            e.printStackTrace();
        }

    }

    class MyCon implements Runnable {

        Socket incoming;

        public MyCon(Socket incoming) {

            this.incoming = incoming;
        }

        @Override
        public void run() {

            try {
                PrintWriter pw = new PrintWriter(incoming.getOutputStream(),
                        true);
                InputStreamReader isr = new InputStreamReader(
                        incoming.getInputStream());
                BufferedReader br = new BufferedReader(isr);
                String inp = null;

                boolean isDone = true;

                System.out.println("TYPE : BYE");
                System.out.println();
                while (isDone && ((inp = br.readLine()) != null)) {

                    System.out.println(inp);
                    if (inp.trim().equals("BYE")) {
                        System.out
                                .println("THANKS FOR CONNECTING...Bye for now");
                        isDone = false;
                        s.close();
                    }

                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                try {
                    s.close();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                e.printStackTrace();
            }

        }

    }

    public static void main(String[] args) {

        new ServerTest().go();

    }

}
于 2012-06-25T15:08:40.783 に答える