質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.04%

Java サーバー・マルチクライアント通信

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 3,336

score 10

Javaサーバークライアント通信についての質問です。

複数のクライアントに対応するサーバーをつくろうとしています。
クライアントと接続されたときに新しくスレッドを作成し、
その中で、サーバー側コンソール入力が行われた場合に、全クライアントに送信するという
処理を書いたのですが、
なぜか、サーバー側(Server.java)の各クライアントスレッドのコメントの部分(質問下部にソースコードを記載しました)にあるように
そこに何かの処理が無いと、その次にあるif文の中に入ってくれないようです。
それはなぜなのでしょうか?

自身の考えとしては、
Modelクラスのdataフィールドに同時にアクセスすることによる何かなのではないかと考えてはいますが、
具体的になぜ起こるのか、などがわかりません。
なぜこのようなことになるのか、また、その対処策を教えていただきたく、質問しました。

よろしくお願いします。


 Server.java

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class Server {
    
    Socket socket;
    ServerSocket server;
    Scanner scan;
    
    public Server() throws Exception {
        server = new ServerSocket(8000);
        scan = new Scanner(System.in);
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        socket = server.accept();
                        new Multi(socket).start();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        
        while (true) {
            System.out.println("書き込みループの中: " + Model.data);
            Model.data = scan.next();
        }
    }
    
    public static void main(String[] args) throws Exception {
        new Server();
    }
    
}


class Multi extends Thread {
    Socket socket;
    ObjectOutputStream oos;
    ObjectInputStream ois;
    PrintWriter out;
    
    String data;
    
    public Multi(Socket _socket) throws Exception {
        socket = _socket;
        System.out.println(socket.getRemoteSocketAddress() + "と接続中");
        out = new PrintWriter(socket.getOutputStream(), true);
    }
    
    @Override
    public void run() {
        System.out.println("スレッドの中");
        while (true) {
            try {
// この文が無いとclient側が認識しない
// sleepでなくても、コンソール出力など何か適当な処理でよい
                sleep(1000);
            } catch (InterruptedException e1) {}
            if (Model.data != null && data != Model.data) {
                data = Model.data;
                try {
                    System.out.println("out.println");
                    out.println(data);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 Client.java

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.net.InetSocketAddress;
import java.net.Socket;

public class Client {
    Socket socket;
    ObjectInputStream ois;
    InetSocketAddress adress;
    BufferedReader in;
    
    String line;
    
    public Client() throws Exception {
        socket = new Socket();
        adress = new InetSocketAddress(8000);
        
        socket.connect(adress);
        System.out.println(socket.getRemoteSocketAddress() + "と接続中");
        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        
        while ((line = in.readLine()) != null) {
            System.out.println("ループの中");
            System.out.println(line);
        }
    }
    
    public static void main(String[] args) throws Exception {
        new Client();
    }
}

 Model.java

public class Model {
    public static String data;
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+3

こちら現象から推測で回答いたします。
間違っていたら読み捨てていただいて構いません。

マルチスレッドは何年も前にやっていたので、
不確かなのですが、現象からするとコンパイラが最適化してしまっているので、
処理が行われないのではないかと思います。

上記が原因であれば、対応方法ですが下記になるかと思います。
volatile String data;

参考になれば幸いです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/04/05 19:09

    ありがとうございます、おっしゃるやり方で実装し直すと、解決しました。
    また、よろしくお願いします。

    キャンセル

0

回答ではありませんが、ひとつ疑問があります。
もしこのプログラムを実際のクライアント/サーバープログラムに適用するとしたら、サーバーとクライアントで同じメモリー領域を共有できないのですから、Model.dataを共有することはできませんね。実際には使わない部分なのでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/04/05 16:13

    すみません、説明不足でした。
    今回のプログラムの場合、Model.dataはサーバーのみで使用します。
    サーバークライアント同士の値の共有のためではありません。

    サーバーでは、常時コンソール入力を受け付け、入力されれば、Model.dataを書き換えます。
    そこでは、まだクライアントには送らずに、サーバー内の別のスレッドで、常時Model.dataを監視し、Model.dataに変化があった場合、クライアント側に送信するという内容になっております。
    このようにする目的は、
    実際はGUIのプログラムを開発しているのですが、その場合、クライアントに送る情報は、
    コンソール入力1種類ではなく、ボタンの押下や、テキストボックスへ入力など様々なものがあり、
    その都度、クライアントに送るのは、まとまりがありません。
    そのために、クライアントに送る場所はあるスレッドのみで、ボタンを押した時などは、Modelクラスを更新するのみとしています。
    (クライアントがサーバーに送るときも同様の処理を行います)

    説明ベタではありますが、ご理解いただけたでしょうか?

    キャンセル

  • 2015/04/05 19:04

    解説ありがとうございます。
    理解しました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.04%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る