0

状況

LAN 内の 2 台のコンピューター間でメッセージを交換するプログラムを作成しています。1 台のコンピューターは自分自身をサーバーとして認識し、もう 1 台はクライアントとして認識します。起動時に、ユーザーは別のコンピューターのホストとポートを入力する必要があります。そのコンピューターにクライアントとして接続する必要があります。それがどのように機能するかのセットアップは非常に基本的です: メッセージを入力して Enter キーを押すと、それが自分の画面に表示されます。その後、会話相手はボタンをクリックして最新のメッセージを取得する必要があり、画面に表示されます。これは誰かが去るまで続きます。

問題

プログラムが正しく起動し、接続設定を求められます。その後、両方のコンピューターで接続を開始すると、問題なく動作しているように見えます (接続が確立されると、クライアントまたはサーバーなどのステータス (1) がラベルに表示されます)。メッセージを入力して送信すると、問題なく動作し続けます。出力は送信者の画面に書き込まれ、予期しない動作は発生しません。

他のコンピューターでメッセージを取得したい場合、プログラムが完全にフリーズします。GUI 内のオブジェクトはクリックできず、出力も表示されません。

コード

接続が正しく確立されていると仮定して ((1) を参照)、メッセージを送信するプロセスの概要を以下に示しますが、重要でない部分は省略します。

GuiApplication.java

private void sendMessage() {
    connection.sendMessage(message);
    showMessage(message);
}

Connection.java
public void sendMessage(String message) {
    if (isClient()) {
        client.sendMessage(message);
    } else if (isServer()) {
        server.sendMessage(message);
    }
}

Client.java
public void sendMessage(String message) {
    outbound = new PrintWriter(socket.getOutputStream(), true); // Defined outside this method
    outbound.println(message);
}

メッセージを送信するプロセスは非常に簡単ですが、何かを見落とした場合に備えて含めたいと思いました。

以下は、新しいメッセージを取得するために作成したコードです。概念は単純です。新しいメッセージがあるかどうかを確認し、ある場合はそれらを取得します。

GuiApplication.java
if (connection.hasNewMessage()) {
    message = connection.retrieveMessage();
}
showMessage(message);

最初の部分 ( connection.hasNewMessage()) は、プログラムがクライアントまたはサーバーを実行しているかどうかを確認し、適切な を呼び出しますretrieveMessage()

Client.java
public String retrieveMessage() throws IOException {
    inbound = socket.getInputStream(); // Defined outside this method
    return IOUtils.toString(inbound, "UTF-8");
}

最初はメソッドBufferedReaderを使用しInputStreamReaderて呼び出すreadLine()ことでこれを試しましたが、commons.io メソッドが機能しないことに気付いたら試してみることにしました (現在直面している問題と同じです)。

質問

新しいメッセージを取得するボタンをクリックした瞬間にプログラムがハングアップするのはなぜですか?

外部の

眉をひそめているかどうかはわかりませんが、必要なコードスニッパーがそこにあると思いますが、より良い概要が必要な場合に備えて、ここに github リポジトリがあります。

4

2 に答える 2

2

すべての説明とすべてのコード添付ファイルを読まなくても、UIスレッドからのストリームの読み取りまたは書き込みを行っていると推測できます(たとえば、アクションからIO操作を呼び出すか、ActionListener直接実行すると、読み取り/書き込みがブロックされます。

コードを調べてください。in.read()またはに電話するポイントが見つかると思いますout.write()。行の直前と直後に印刷を追加します。読み取りまたは書き込みを終了しないことがわかります。

これは、反対側が反対の操作を実行しないためです。したがって、次のことを行う必要があります。

  1. UIをIOから切り離します。IOは別のスレッドで実行する必要があります。
  2. 反対側が流れを妨げる理由を確認してください。
于 2012-12-23T16:00:48.130 に答える
2

私はあなたのコードを見ましたが、私が疑ったように、あなたの問題はあなたが投稿したコードとはまったく関係がありません. GUI は Swing スレッド化ルールを完全に無視し、イベント ディスパッチ スレッドまたは EDT として知られるメインの Swing イベント スレッドで実行時間長いタスク呼び出します。このスレッドはすべての Swing 描画とユーザー操作を担当するため、GUI はこれを実行できず、完全にフリーズします。

詳細については、Swing の同時実行を参照してください。

そして次回は、sscceを投稿してください。そうすれば、大量のソース コードに飛び込む必要がなくなります。SSCCE の鍵は、目前の問題に不可欠ではないすべてのコードを排除することです。これを行うのは簡単ではなく、作成するには多くの作業が必要になるため、実行するのに十分なコードが必要になりますが、コードに溺れるほどではありませんが、ボランティアに無料で手伝ってくれるように頼んでいます.時間なので、あまり求めていません。

頑張ってください!

于 2012-12-23T16:15:41.083 に答える