sykwer/cli_chat

Client Specification

Opened this issue · 4 comments

以下は #1 からのコピペ

機能実装(クライアント)

  • chatlogin -to <ipaddress:port> -as <username> コマンドで, クライアントはホストとのsocket通信を確立する. 現在のスレッドでは, stdinで入力を待つようにし, 別スレッドでsocketからのinputstreamを待ち, stdoutに出力するようにする.
    • socket通信が確立した直後に, login <username>という書式で, socketのoutputstreamに書き込む.
  • stdinに入力されたメッセージは, validationをした上で, そのままsocketのoutputstreamに書き込む.
    • validationは, 許可されているコマンドかを調べる.
      • send <message> (他の人にメッセージをブロードキャストする)
      • logout (streamへの書き込みをしたのち, socket通信を終了する)
  • 別スレッドで, socketからのinputstreamを受け取ったら, そのままstdoutに出力する.

https://codezine.jp/article/detail/193

クラス設計

今回、クライアントは一つしか使わないので、基本的にシングルトンで実装します。
シングルトンとは、インスタンスを一つしか作らない実装方針のことです。
このサイトを見ると、シングルトンってなに?ってことがわかりやすいかと思います。
http://www.techscore.com/tech/DesignPattern/Singleton.html/

Socketを用いて、クライアントとサーバーは通信を行います。
image

◎ChatClient

○役割

  • ユーザーからの標準入力を受け取り、ChatSenderに渡す。
  • ChatReceiverからの入力を受け取り、コンソール上に標準出力する。

◎ChatReceiver

○役割

サーバー側からのメッセージを受け取る。

◎ChatSender

○役割

サーバー側にメッセージを送信する。

todo

  • エラーハンドリング
    • ChatReceiver, ChatSenderのIOExceptionの処理はどのクラスが持つか.
    • IOExceptionの場合ごとにエラーハンドリング.
  • コマンド処理

送るクラス

import java.io.IOException;
import java.net.Socket;

class ChatSender {
    private static ChatSender singleton = new ChatSender();

    private ChatSender() {
    }

    static ChatSender getSender() {
        return singleton;
    }

    // TODO: 2018/05/13 実装 
    void sendMessage(Socket socket, String message) throws IOException {
    }
}

参考になりそうなコード

//送信するメッセージは以下の行に記述されているもの。
String message = "チャット接続送信テスト。";
PrintWriter writer = new PrintWriter(socket.getOutputStream());
System.out.println("送信メッセージ: " + message);
writer.println(message);
writer.close();

受け取るクラス

import java.io.IOException;
import java.net.Socket;

class ChatReceiver {
    private static ChatReceiver singleton = new ChatReceiver();

    private ChatReceiver() {
    }

    static ChatReceiver getReceiver() {
        return singleton;
    }

    // TODO: 2018/05/13 実装 
    void waiteForMessage(Socket socket) throws IOException {
    }
}

参考になりそうなコード

InputStream input = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
while (!socket.isClosed()) {
     String line = reader.readLine();
     System.out.println(line);
}

https://stackoverflow.com/questions/484925/does-closing-the-bufferedreader-printwriter-close-the-socket-connection

Yes, closing any Writer/Reader will close all other Writers and Readers that they wrap. Don't close it until you are ready to close the underlying socket.