Каков наилучший способ управления текстовыми клиент-серверными соединениями? - PullRequest
2 голосов
/ 18 апреля 2011

Я хочу написать небольшую клиент-серверную текстовую игру, которая обрабатывает несколько клиентских подключений и постоянно влияет на состояние игры.Мне интересно, как лучше всего обрабатывать несколько соединений, чтобы команды обрабатывались в порядке их поступления на сервер.

В идеале я не собираюсь использовать преимущества многопоточности, по крайней мерена уровне обработки команд.Я был бы согласен с каждым клиентом, имеющим отдельный поток (чтобы иметь блокировку ввода-вывода в каждом потоке), до тех пор, пока я мог бы объединить обработку в одном потоке после этого.и сервер будет текстовым, я не уверен, как лучше настроить связь.Если бы я выбрал блокирующий ввод-вывод, как бы я поставил в очередь обработку в одном потоке?

В качестве альтернативы, если бы я выбрал неблокирующий ввод-вывод и использовал селектор для запроса, когда клиенты писали на сервер,Как я могу получить строку неизвестной / неограниченной длины без использования ByteBuffer установленного размера?Неблокирование также способствует сохранению обработки в одном потоке, поскольку она может просто считывать данные с клиентских подключений по мере того, как они отправляют новые данные.Однако, когда я попытался реализовать его с помощью read / writeUTF, я столкнулся с IllegalBlockingModeException heh.

Любые ответы на вопросы или предложения о том, как сделать это способом, который я не упомянул, будут искренне оценены.!Я довольно новичок в работе с клиентами и серверами, поэтому не знаю, будут ли наиболее подходящими java.io или java.nio.

Извините за запутанный вопрос.Я думаю, что сбежал с собой.

Ответы [ 2 ]

1 голос
/ 18 апреля 2011

Мнения расходятся, но я бы определенно использовал один поток для каждого клиента.Связь с одним потоком обработки может затем проходить через LinkedBlockingQueue или просто синхронизированный LinkedList.

Что-то вроде этого в потоке для каждого клиента:

public class Client implements Runnable, ResponseOutput {

    private final BufferedReader br;
    private final PrintWriter pw;

    public Client(Socket s) {
        br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        pw = new PrintWriter(s.getOutputStream());
    }

    // defined by the ResponseOutput interface
    public void sendReply(String reply) {
        pw.println(reply);
    }

    public void run() {
        try {
            while (true) {
                String s = br.readLine();
                if (s==null)
                    break;
                Processor.queue(new Processor.InputItem(this, s));
            }
        } catch (IOException ioe) {
            ... error handling ...
        }
    }
}

Затем это для обработки:

public class Processor implements Runnable {
    static public class InputItem {
        final ResponseOutput client;
        final String command;

        public InputItem(ResponseOutput client, String command) {
            this.client = client;
            this.command = command;
        }
    }

    static private Processor instance;
    static public void queue(InputItem item) {
        instance.commandQueue.add(item);
    }

    private BlockingQueue<InputItem> commandQueue;

    public void run() {
        try {
            while (true) {
                InputItem item = commandQueue.take();
                String reply = doStuff(item.command);
                item.client.sendReply(reply);
            }
        } catch (InterruptedException ie) {
            ... error handling ....
        }
    }
}

В классе InputItem вы также можете включить ссылку на любое игровое состояние, которое требует обновления.Поскольку его изменяет только поток обработки, вы можете сделать это без какой-либо синхронизации.

1 голос
/ 18 апреля 2011

Я не эксперт в области клиентских систем, но я поделюсь парой советов

В зависимости от ваших потребностей, вы можете просто настроить сервер Tomcat и выполнить http-запрос, это довольно просто и, конечно, все на Java.

недостаток в том, что запрос может быть немного медленным.

Второй вариант, который вы можете проверить, это RMI.

Концепция проста: вы подключаетесь к другому компьютеру, а когда это делается, вы вызываете методы на другом компьютере из локального объекта в вашем коде.

http://java.sun.com/developer/onlineTraining/rmi/RMI.html

это может показаться немного сложным (а иногда отладка стека на нескольких компьютерах немного сложнее), но я рекомендую, потому что это сохраняет ваш код чистым.

Наконец, вы можете попробовать сокеты, но сами по себе: P

...