Почему я должен использовать NIO для многопользовательской игры TCP вместо простых сокетов (IO) - или: где блок? - PullRequest
3 голосов
/ 05 января 2012

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

Почти везде (и здесь) вы получаете рекомендацию использовать NIO или среду, в которой используется NIO, из-за «блокировки».Я пытаюсь понять, в чем проблема простой реализации сокетов, поэтому я создал простой тест для проверки:

Мое основное приложение:

[...]
Socket clientSocket = new Socket( "127.0.0.1", 2593 );
new Thread(new PacketReader(clientSocket)).start();
PrintStream os = new PrintStream( clientSocket.getOutputStream() );
os.println( "kakapipipopo" );
[...]

Поток PacketReader:

class PacketReader implements Runnable
{
    Socket m_Socket;
    BufferedReader m_Reader;

    PacketReader(Socket socket)
    {
        m_Reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    }

    public void run()
    {
        char[] buffer = new char[200];
        int count = 0;
        while(true)
        {
            count = m_Reader.read(buffer, 0, 200);
            String message = new String(buffer, 0, count);
            Gdx.app.log("keks", nachricht);
        }
    }
}

Я не мог испытать проблемы с блокировкой, которые я должен получить.Я думал, что функция read () заблокирует мое приложение, и я ничего не мог сделать, но все работало просто отлично.Я думал: что, если я просто создаю входной и выходной буфер в своем приложении и создаю два потока, которые будут записывать и читать в сокет из моих двух буферов?Будет ли это работать?Если да - почему все рекомендуют NIO?Где-то в нормальном режиме ввода-вывода должен произойти блок, но я не могу его найти.Есть ли другие преимущества использования многопользовательских игр NIO для Android?Я думал, что NIO кажется более сложным, поэтому, возможно, менее подходящим для мобильного устройства, но, возможно, простой способ сокетов хуже для мобильного устройства.проблема случается.Я не боюсь NIO, но, по крайней мере, я хотел бы узнать, почему я его использую: D

Привет

-Thomas

Ответы [ 2 ]

0 голосов
/ 06 мая 2017

РЕДАКТИРОВАТЬ Этот ответ является своего рода не совсем точным ответом на вопрос, заданный ОП.Для клиентской стороны это хорошо, потому что клиент собирается подключиться только к одному серверу.Хотя мой ответ дает общее представление о блокирующем и неблокирующем вводе-выводе.

Я знаю, что этот ответ придет через 3 года, но это то, что может кому-то помочь в будущем.модели, если данные недоступны для чтения или если сервер не готов к записи, сетевой поток будет ожидать запроса на чтение или запись в сокет, пока не получит или не отправит данные или не истечет время ожидания.Другими словами, программа может остановиться в этот момент на некоторое время, если она не может продолжаться.Чтобы отменить это, мы можем создать поток для каждого соединения, который может обрабатывать запросы от каждого клиента одновременно.Если выбран этот подход, масштабируемость приложения может пострадать, потому что в сценарии, где подключены тысячи клиентов, тысячи потоков могут поглотить всю память системы, поскольку потоки являются дорогостоящими в создании и могут влиять на производительностьapplication.

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

Диаграмма ниже объясняет разницу между блокирующей и неблокирующей моделью сокетов.enter image description here

0 голосов
/ 12 декабря 2014

Блокировка: read () будет блокировать текущий поток до тех пор, пока он не сможет прочитать данные из входного потока сокета. Таким образом, вам нужен поток, выделенный для этого единственного TCP-соединения.

Что делать, если к вашему серверу подключено более 10 тысяч клиентских устройств? Вам нужно как минимум 10 тыс. Потоков для обработки всех клиентских устройств (предположим, что каждое устройство поддерживает одно TCP-соединение) независимо от того, активны они или нет. У вас слишком много накладных расходов на переключение контекста и другие многопоточные издержки, даже если активны только 100 из них.

NIO использует модель селектора для обработки этих клиентов, что означает, что вам не требуется выделенный поток для каждого TCP-соединения для получения данных. Вам просто нужно выбрать все активные соединения (в которых уже есть данные) и обработать эти активные соединения. Вы можете контролировать, сколько потоков следует поддерживать на стороне сервера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...