Netty - Как проверить номера версий клиент / сервер - PullRequest
1 голос
/ 16 января 2012

Как часть моего протокола, я бы хотел, чтобы клиент отправлял свой номер версии при установлении нового соединения. Я хотел бы, чтобы это было сделано в отдельном обработчике в конвейере, поэтому, пожалуйста, потерпите меня, так как это может быть довольно простой вопрос, но я не уверен, как это сделать. Другое дело, что я хотел бы затем иметь возможность отправлять POJO туда и обратно через соединение (конвейер). Также я хотел бы добавить обработчик аутентификации. В любом случае, сейчас я получаю какую-то ошибку, и я почти уверен, что это потому, что проверка версии не была правильно обработана из конвейера.

В основном код, который я имею ниже, настроен для отправки «Hello World», который сервер распечатывает после проверки версии после установления соединения. По крайней мере, в теории, на самом деле это не совсем работает;)

В настоящее время у меня есть:

Client.java

public static void main(String[] args)
{
    ...

    // Set up the pipeline factory.
    bootstrap.setPipelineFactory(new ChannelPipelineFactory() 
    {
        @Override
        public ChannelPipeline getPipeline() throws Exception 
        {
            return Channels.pipeline(
                    new ObjectEncoder(),
                    new ObjectDecoder(),
                    new VersionClientHandler(),
                    new BusinessLogicClientHandler());
        }
    });     

    ...

    // The idea is that it will all be request and response. Much like http but with pojo's. 
    ChannelFuture lastWriteFuture = channel.write("Hello world".getBytes());

    if (lastWriteFuture != null) 
    {
        System.out.println("waiting for message to be sent");
           lastWriteFuture.awaitUninterruptibly();
    }

    ...
}

VersionClientHandler.java

public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
{
    ChannelBuffer versionBuffer = ChannelBuffers.buffer(VERSION_STRING_LENGTH);
    versionBuffer.writeBytes("v123.45a".getBytes());
    // If I understand correctly, the next line says use the rest of the stream to do what you need to the next Handler in the pipeline?
    Channels.write(ctx, e.getFuture(), versionBuffer);  
}

BusinessLogicClientHandler.java

Not really doing anything at this point. Should it?

Server.java

public static void main(String[] args)
{
    ...

    public ChannelPipeline getPipeline() throws Exception 
    {
        return Channels.pipeline(
                new ObjectEncoder(),
                new ObjectDecoder(),
                new VersionServerHandler(),
                new BusinessLogicServerHandler());
    }

    ...
}

VersionServerHandler.java

public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) 
{
    ChannelBuffer versionBuffer = ChannelBuffers.buffer(VERSION_NUMBER_MAX_SIZE);
    System.out.println("isReadable - messageReceived: " + versionBuffer.readable()); // returns false???
    // Basically I want to read it and confirm the client and server versions match.
    // And if the match fails either send a message or throw an exception
    // How do I also pass on the stream to the next Handler? 
}

BusinessLogicServerHandler.java

public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) 
{
    e.getMessage();
    byte[] message = (byte[])e.getMessage(); // "Hello World" in byte[] from Client.java
}

Итак, в основном я хочу, чтобы номер версии передавался и проверялся, когда канал подключен как часть протокола связи. Все делается автоматически за кадром. Точно так же я хотел бы передать механизм аутентификации таким образом.

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

Ответы [ 4 ]

2 голосов
/ 21 января 2012

Я нашел решение !!!

Был ряд проблем.

В VersionClientHandler новый код:

public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
{
    String verison = "v123.45a";

    ChannelBuffer versionBuffer = ChannelBuffers.buffer(VERSION_STRING_LENGTH);
    versionBuffer.writeBytes(version.getBytes());
    e.getChannel().write(version);
}

Обратите внимание на последнюю строку e.getChannel().write(version); вместо Channels.write(ctx, e.getFuture(), versionBuffer); Я не уверен, почему, На самом деле, я собираюсь начать изучать, почему у меня есть код ChannelBuffers, потому что он, похоже, ничего не делает ...

На VersionServerHandler.java Iтеперь есть:

public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) 
{
    String versionCheck = (String)e.getMessage();
    System.out.println("VersionServerHandler - " + versionCheck);
    ctx.getPipeline().remove(VersionServerHandler.class);
}

Заметьте, я больше не читаю через буфер, я просто делаю e.getMessage() и приводим к нужному типу объекта.Выше я добавил ctx.getPipeline().remove(VersionServerHandler.class);, чтобы убрать этот обработчик из дальнейшей обработки.Больше не требуется после первоначального подключения.Спасибо Деннису за этот совет.

Заключение

Остальное - это как я и ожидал.ключ в том, что я не правильно понял, как читать буферы и передавать информацию.И сообщения об ошибках и примеры были не совсем понятны.Как только вы добавите каналы POJO из Netty в свой конвейер, вам нужно начать работать только с объектами, для всех обработчиков.Я скучал по этому.Концепции были правильными, просто я попытался прочитать данные с каналов, что было неверным.

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

0 голосов
/ 21 января 2012

Я создал простой пример: https://github.com/boldt/netty-examples/

Возвращает номер версии, когда устанавливается новое соединение. Это делается в отдельном обработчике, который будет удален из конвейера после записи версии на канале. После этого это пример ECHO из учебника по netty.

A telnet localhost 1234 на сервере сразу показывает версию.

Таким образом, вы можете добавить обработчик аутентификации в конвейер за обработчиком версий.

0 голосов
/ 21 января 2012

Я думаю, что вы хотите, чтобы можно было легко заархивировать, добавив несколько пользовательских обработчиков. Таким образом, для проверки версии вы можете добавить обработчик, который переопределяет channelConnected (....) и выполнить проверку там. Для аутентификации просто добавьте еще один обработчик после проверки версии, который переопределяет метод messageReceve (....). После завершения аутентификации вы можете удалить обработчик из конвейера и добавить его обратно, как только он понадобится снова.

Обработчик BusinessLogic должен находиться в конвейере как последний. Просто имейте в виду, что любой из ваших обработчиков выполняет некоторую блокирующую операцию, вам следует подумать о добавлении перед ним ExecutionHandler, чтобы быть уверенным, что поток ioworker не будет заблокирован, и, таким образом, сделает сервер netty безответственным.

0 голосов
/ 16 января 2012

Вы не упомянули, в чем заключается ошибка, которую вы видите.

В любом случае, я бы не рекомендовал использовать отдельный обработчик каналов для проверки версии.Главным образом потому, что проверка версии должна производиться только один раз, когда соединение устанавливается впервые.Кроме того, я думаю, что обработчикам каналов лучше всего заниматься проблемами транспортного уровня, например преобразованием байтов в pojos.

...