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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

5120閲覧

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

meriyasu

総合スコア8

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2015/04/04 18:57

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

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

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

よろしくお願いします。

Server.java

lang

1import java.io.IOException; 2import java.io.ObjectInputStream; 3import java.io.ObjectOutputStream; 4import java.io.PrintWriter; 5import java.net.ServerSocket; 6import java.net.Socket; 7import java.util.Scanner; 8 9public class Server { 10 11 Socket socket; 12 ServerSocket server; 13 Scanner scan; 14 15 public Server() throws Exception { 16 server = new ServerSocket(8000); 17 scan = new Scanner(System.in); 18 19 new Thread(new Runnable() { 20 @Override 21 public void run() { 22 while (true) { 23 try { 24 socket = server.accept(); 25 new Multi(socket).start(); 26 } catch (Exception e) { 27 e.printStackTrace(); 28 } 29 } 30 } 31 }).start(); 32 33 while (true) { 34 System.out.println("書き込みループの中: " + Model.data); 35 Model.data = scan.next(); 36 } 37 } 38 39 public static void main(String[] args) throws Exception { 40 new Server(); 41 } 42 43} 44 45 46class Multi extends Thread { 47 Socket socket; 48 ObjectOutputStream oos; 49 ObjectInputStream ois; 50 PrintWriter out; 51 52 String data; 53 54 public Multi(Socket _socket) throws Exception { 55 socket = _socket; 56 System.out.println(socket.getRemoteSocketAddress() + "と接続中"); 57 out = new PrintWriter(socket.getOutputStream(), true); 58 } 59 60 @Override 61 public void run() { 62 System.out.println("スレッドの中"); 63 while (true) { 64 try { 65// この文が無いとclient側が認識しない 66// sleepでなくても、コンソール出力など何か適当な処理でよい 67 sleep(1000); 68 } catch (InterruptedException e1) {} 69 if (Model.data != null && data != Model.data) { 70 data = Model.data; 71 try { 72 System.out.println("out.println"); 73 out.println(data); 74 } catch (Exception e) { 75 e.printStackTrace(); 76 } 77 } 78 } 79 } 80}

Client.java

lang

1import java.io.BufferedReader; 2import java.io.InputStreamReader; 3import java.io.ObjectInputStream; 4import java.net.InetSocketAddress; 5import java.net.Socket; 6 7public class Client { 8 Socket socket; 9 ObjectInputStream ois; 10 InetSocketAddress adress; 11 BufferedReader in; 12 13 String line; 14 15 public Client() throws Exception { 16 socket = new Socket(); 17 adress = new InetSocketAddress(8000); 18 19 socket.connect(adress); 20 System.out.println(socket.getRemoteSocketAddress() + "と接続中"); 21 in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 22 23 while ((line = in.readLine()) != null) { 24 System.out.println("ループの中"); 25 System.out.println(line); 26 } 27 } 28 29 public static void main(String[] args) throws Exception { 30 new Client(); 31 } 32}

Model.java

lang

1public class Model { 2 public static String data; 3}

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

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

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

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

volatile String data;

参考になれば幸いです。

投稿2015/04/05 04:13

kiri

総合スコア74

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meriyasu

2015/04/05 10:09

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

0

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

投稿2015/04/05 05:01

argius

総合スコア9390

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meriyasu

2015/04/05 07:13

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

2015/04/05 10:04

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問