Package com.javachat.client

Source Code of com.javachat.client.ChatClient

package com.javachat.client;

import com.javachat.shared.Command;
import com.javachat.shared.Logger;
import com.javachat.shared.MessageHolder;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

/**
* Java chat клиент
*
* @author Dmitry Levykin
*/
public class ChatClient {
    // Кодировка сообщений
    public static final String CHARSET_NAME = "UTF-8";
    // Максимальный размер одного сообщения 1 Кб
    private static final int MESSAGE_LIMIT = 1024;
    // Буфер приема 1 Кб
    private final ByteBuffer buffer = ByteBuffer.allocate(1024);
    // Буфер для хранения частей сообщений
    private ByteBuffer endBuffer = null;
    // Накопитель отдельного сообщения
    private MessageHolder holder;

    // Флаг запуска и подключения
    private boolean start = false;
    // Канал связи
    private SocketChannel channel;
    // Поток ввода текста
    private InputStream inputStream;
    //
    private BufferedReader bufferedReader;

    // Имя клиента
    private String userName;
    // Порт по-умолчанию
    private Integer port = 3000;
    // Хост по-умолчанию
    private String host = "localhost";

    /**
     * Java chat клиент
     *
     * @param userName    Имя пользователя, может быть null
     * @param inputStream Поток ввода
     */
    public ChatClient(String userName, String host, Integer port, InputStream inputStream) {
        if (inputStream == null) {
            throw new IllegalArgumentException("InputStream is not set!");
        }
        this.userName = userName;
        this.host = host == null ? this.host : host;
        this.port = port == null ? this.port : port;
        this.inputStream = inputStream;
    }

    public static void main(String[] args) throws InterruptedException {
        Logger.info("Java chat client.");

        // DEBUG OFF
        Logger.setDebugMode(false);

        String userName = null;
        String host = null;
        Integer port = null;
        // Параметры приложения
        if (args != null && args.length != 0 && args.length % 2 == 0) {
            for (int i = 0; i < args.length / 2; i++) {
                String key = args[i * 2];
                String value = args[i * 2 + 1];
                switch (key) {
                    case "-n":
                        userName = value;
                        Logger.debug("Parameter user name is %s.", userName);
                        break;
                    case "-h":
                        host = value;
                        Logger.debug("Parameter host is %s.", host);
                        break;
                    case "-p":
                        port = Integer.valueOf(value);
                        Logger.debug("Parameter port is %d.", port);
                        break;
                }
            }
        } else {
            Logger.info("Optional parameters: \n" +
                    "-n User\n" +
                    "-h Host\n" +
                    "-p Port\n");
        }
        // Запуск клиента с вводом из консоли
        new ChatClient(userName, host, port, System.in).start();
    }

    /**
     * Отключение и остановка потока-слушателя сокета
     */
    void shutdown() {
        if (!start) {
            return;
        }
        start = false;
        try {
            if (channel != null) {
                channel.close();
            }
        } catch (IOException e) {
            // Ignore
        }
    }

    /**
     * Создание канала связи
     */
    void createChannel() throws IOException {
        channel = SocketChannel.open();
        channel.connect(new InetSocketAddress(host, port));
        channel.configureBlocking(false);
    }

    /**
     * Отправка сообщения на сервер
     */
    void sendMessage(String message) throws IOException {
        sendMessage(message.getBytes(CHARSET_NAME));
    }

    /**
     * Отправка массива байт сообщения на сервер
     */
    void sendMessage(byte[] messageBytes) throws IOException {
        ByteBuffer buffer = ByteBuffer.allocate(messageBytes.length + 4);
        buffer.putInt(messageBytes.length);
        buffer.put(messageBytes);
        buffer.flip();
        channel.write(buffer);
    }

    /**
     * Установка ввода
     */
    void setInputStream(InputStream inputStream) {
        bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
    }

    /**
     * Запуск основного цикла клиента
     */
    void start() throws InterruptedException {
        if (start) {
            return;
        }

        Logger.debug("Try connect to %s:%d.", host, port);
        try {
            createChannel();
            start = true;
            Logger.debug("Connect success.");

            setInputStream(inputStream);

            // Авторизация, если параметр задан
            if (userName != null) {
                sendMessage(Command.LOGIN.getText() + userName);
            }

            while (start && !channel.socket().isClosed()) {
                // Неблокирующий ввод из inputStream
                if (bufferedReader.ready()) {
                    String message = bufferedReader.readLine();
                    sendMessage(message);
                    // Обработка команды выхода
                    if (message.trim().equals(Command.QUIT.getText())) {
                        start = false;
                    }
                }

                // Чтение сообщений с сервера
                if (onRead() == null) {
                    Thread.sleep(200);
                }
            }
        } catch (IOException e) {
            Logger.info("Client start error: " + e.getMessage() + ".");
            // Остановка
            shutdown();
        }
    }

    /**
     * Получение и обработка сообщений с севера
     */
    String onRead() throws IOException {
        if (holder == null) {
            holder = new MessageHolder(MESSAGE_LIMIT, CHARSET_NAME);
        }
        if (endBuffer != null && endBuffer.hasRemaining()) {
            buffer.put(endBuffer);
        }
        if (channel.read(buffer) == -1) {
            throw new IOException("End of server stream!");
        }
        buffer.flip();
        String message = holder.readFromBuffer(buffer);
        if (message != null) {
            Logger.info(message);
            holder = null;
        }
        if (buffer.hasRemaining()) {
            endBuffer = ByteBuffer.allocate(buffer.remaining());
            endBuffer.put(buffer);
            endBuffer.flip();
        }
        buffer.clear();
        return message;
    }
}
TOP

Related Classes of com.javachat.client.ChatClient

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.