0

Java プログラムに問題があります。私はこのコードを持っています:

Host.java :

public class Host {
protected static void start(JFrame window) {
    ServerSocket server = null;
    try {
        server = new ServerSocket();
        SocketAddress addr = new InetSocketAddress(hostname, port);
        server.bind(addr);

        Socket socket = server.accept();

        window.setVisible(false);

        Thread thread = new Thread(new Incomming(socket.getInputStream()));
        thread.start();
        thread.join();

        socket.close();
    } catch (UnknownHostException e) {
        [...]
}
}

Incoming.java :

public class Incomming implements Runnable {
private DataInputStream is;

public Incomming(InputStream is) {
        MyFrame frame = new MyFrame();
    frame.setVisible(true);
    frame.pack();

    this.is = new DataInputStream(is);
}

public void run() {
    try {
        while(!Thread.currentThread().isInterrupted()) {
            int n = is.readInt();
            if(n == -1) {
                break;
            }
            byte[] b = new byte[n];
            is.readFully(b);
            [...] // working with bytes
        }
        System.out.println("Stream closed.");
    } catch(IOException e) {
        [...]
    }
}
}  

Client.javaは Host.java と非常に似ており、socket.getInputStream() にも Incomming.java を使用します。

したがって、問題は次のとおりです。クライアントはホストに接続しますが、サーバー側とクライアント側でMyFrameウィンドウを表示する必要がある場合、完全にロードされません。また、古い JFrame ウィンドウ (両側) の閉じるボタンは何もしません。

で行を削除しようとするとthread.join()、MyFrame ウィンドウが完全に読み込まれ、閉じるボタンが機能しsocket closedますが、メッセージで例外がスローされるため、クライアントはホストに接続されなくなります。

この問題を解決するにはどうすればよいですか? 返信ありがとうございます。

4

3 に答える 3

0
  1. thread.join() は、スレッドが終了するまで現在のスレッドをブロックします
  2. socket.close(); スレッドが終了する前に実行されます。このコード ブロックをスレッドの run() メソッドに移動する必要があります。
于 2013-07-12T08:32:18.537 に答える
0

プログラムを作成した方法は、実行の単一の「パス」があることを意味します。2 つのスレッドが同時に処理を行うことは決してありません。これはthread.join()、スレッドが終了するのを待機する を呼び出したためです。クラス内のコードが実行されているか、クラス外のコードが実行されていることを意味しますIncomming

UI をロードするには、一度に 2 つのスレッドを実行する必要があります。これは、ネットワーク接続の処理方法を再考することを意味します。

最初のステップは、Incommingクラス内でソケットのクローズを処理することです。これSocketClosedExceptionにより、閉じられたソケットから読み取ろうとすることによって引き起こされた問題が解決されます。

2番目にできることは、UIとIncommingクラスの間で異なる方法で通信することです。スレッド割り込みは、長時間実行されているネットワーク読み取りからスレッドを起動するための良い方法ですが、スレッドを起動している理由に関する情報を提供しません. これを行う最も簡単な方法はIncomming、関数を呼び出すときに設定されるクラスにブール値フラグを設定することです。

例(疑似コードを許してください):

class Incomming

    Socket socket;
    volatile boolean running;

    run():
        while( running ){ 
            try {
                 /* stuff */
            }catch( InterruptedException e ){
                 // nothing here
                 // we are just waking up the
                 // thread to unblock io
            }
        }
        socket.close()

    stop():
        running = false;
于 2013-07-11T20:42:21.857 に答える