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

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

ただいまの
回答率

90.98%

  • Java

    12213questions

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

  • ネットワーク

    461questions

    ネットワークとは、複数のコンピューター間を接続する技術です。インターネットが最も主流なネットワークの形態で、TCP/IP・HTTP・DNSなどの様々なプロトコルや、ルータやサーバーなどの様々な機器の上に成り立っています。

  • マルチスレッド

    46questions

    マルチスレッドは、どのように機能がコンピュータによって実行したのかを、(一般的にはスレッドとして参照される)実行の複合的な共同作用するストリームへ区分することが出来ます。

javaでチャットサーバの作成でリアルタイムな送受信が行えない

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 503

alice-R

score 12

javaを用いて複数人のチャットサーバの作成を行っています。

・echoサーバーとクライアントのサンプルを元に作成しています。
・echoサーバーに接続を行ったクライアントの順番に、0から番号を割り振っています。
・送信の際は、「'クライアントに割り振った番号' '送信内容'」の形式で送信を行います
・クライアントがechoサーバーに接続した場合、スレッドを起動するマルチスレッドで作成しています。

手順
①二つのクライアント(A,B)からチャットサーバーに接続を行います
②クライアントAからクライアントBに対して送信(A->B)
③クライアントBからクライアントAに対して送信(B->A)

問題点
・②終了時、チャットサーバーに送信内容のログは表示されるのですが、
クライアントB側で受信されません。
・③終了時、先ほど送信した(A->B)の送信内容をクライアントBで受信します。

どのように行えば、リアルタイムに送受信を行うことが出来るのでしょうか。
どなたかご教示の程、どうぞよろしくお願いいたします。

ChatServer

import java.net.Socket;
 import java.net.ServerSocket;
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
 import java.io.IOException;

 public class ChatServer {

  public static final int ECHO_PORT = 10007;
  private static ChatServer CS = new ChatServer();

  public static ChatServer getInstance(){
      return CS;
  }

  public static void start() {
    ServerSocket serverSocket = null;
    Manager manager = null;
    manager = Manager.getInstance();

    try {
      serverSocket = new ServerSocket(ECHO_PORT);
      System.out.println("EchoServerが起動しました(port="
                         + serverSocket.getLocalPort() + ")");
      while (true) {
        Socket socket = serverSocket.accept();
        new EchoThread(socket).start();
        manager.setVal("member",socket);
      }
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      try {
        if (serverSocket != null) {
          serverSocket.close();
        }
      } catch (IOException e) {}
    }
  }
}

class EchoThread extends Thread {

  private Socket socket;

  public EchoThread(Socket socket) {
    this.socket = socket;
    System.out.println("接続されました "
                       + socket.getRemoteSocketAddress());
  }

  public void run() {
    try {
      BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
      PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
      String line;
      while ( (line = in.readLine()) != null ) {
        System.out.println(socket.getRemoteSocketAddress()
                           + " 受信: " + line);
        //out.println(line);
        send(line);
      }
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      try {
        if (socket != null) {
          socket.close();
        }
      } catch (IOException e) {}
      System.out.println("切断されました "
                         + socket.getRemoteSocketAddress());
    }
  }

  public void send(String line){
      Manager manager = null;
      manager = Manager.getInstance();
      String sendTo = line.split(" ",0)[0];
      OutputStream ret = null;
      Socket socket = null;
      try {
          socket = (Socket)manager.getVal(sendTo);
          BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
          ret = socket.getOutputStream();
          PrintWriter out = new PrintWriter(ret, true);
          out.println(line);
      }catch (IOException e) {
          e.printStackTrace();
      } 
  }
}

Client

import java.net.Socket;
 import java.net.ServerSocket;
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.io.IOException;

 public class Client {

  public static final int ECHO_PORT = 10007;

  public static void main(String args[]) {
    Socket socket = null;
    try {
      socket = new Socket("localhost", ECHO_PORT);
      System.out.println("接続しました"
                         + socket.getRemoteSocketAddress());
      BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
      PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
      BufferedReader keyIn = new BufferedReader(new InputStreamReader(System.in));
      String input;
      while ( (input = keyIn.readLine()).length() > 0 ) {
        System.out.println("input now");
        out.println(input);
        String line = in.readLine();
        if (line != null) {
          System.out.println(line);
        } else {
            System.out.println("break");
          break;
        }
      }
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      try {
        if (socket != null) {
          socket.close();
        }
      } catch (IOException e) {}
      System.out.println("切断されました "
                         + socket.getRemoteSocketAddress());
    }
  }
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+3

クライアントの作りに問題があると思います。

クライアントでの受け取るべきデータには次の2つがあります。

  1. そのクライアントを利用しているユーザーからの標準入力
  2. 他のクライアントから送信されたメッセージ

クライアントの作りでは1., 2.を順番に同期的にreadしてますので、例えば1の実行中は2が到達していても何も表示されないのは当然です。複数のクライアントから同時に複数のメッセージが到着しても1を1行入力する度に2で受信できるメッセージは1行だけですから、チャットプログラムの基本構造として成立してないように感じます。

普通は、1と2を別々のスレッドで並行して行う(A)ようにするか1,2を同時に待つ(B)ようにして対処します。(B)はjava.nio.channels.Selectorのような仕組みで達成可能な気がしますが自分は詳細を調べたことがないので本当かどうか自信ないです。一方(A)なら簡単です。

またCUIでやるには少々無理があると思います。キーボードから入力中に標準出力へ他者からのメッセージが表示されてしまうといったいどうなってしまうのでしょうか?それはコンソールとして何を使うかによって振る舞いがかわりそうです。自分ならこのクライアントはGUIアプリにします。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/10/23 20:07

    早々にご回答ありがとうございます。
    全然分からなかったのでこれで進められそうです。
    本当にありがとうございました。

    キャンセル

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

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

関連した質問

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

  • Java

    12213questions

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

  • ネットワーク

    461questions

    ネットワークとは、複数のコンピューター間を接続する技術です。インターネットが最も主流なネットワークの形態で、TCP/IP・HTTP・DNSなどの様々なプロトコルや、ルータやサーバーなどの様々な機器の上に成り立っています。

  • マルチスレッド

    46questions

    マルチスレッドは、どのように機能がコンピュータによって実行したのかを、(一般的にはスレッドとして参照される)実行の複合的な共同作用するストリームへ区分することが出来ます。