2012-01-16 5 views
1

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

В основном код, который у меня ниже, предназначен для отправки «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 
} 

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

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

ответ

2

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

Был ряд вопросов.

На 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 теперь у меня есть:

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

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

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

+0

Мое мышление было обработчиком проверки версии, обработчиком аутентификации, обработчиком для шифрования и обработчиком фактической бизнес-логики. –

+0

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

+0

Это хороший момент. Итак, какова была ошибка, которую вы видите? –

0

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

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

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

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

+0

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

+0

Кроме того, вы можете заставить клиента отправить второе сообщение сразу после этого, скажем, строку, в которой говорится «привет мир», что сервер способен глотать. Если бы вы это сделали, я бы дал вам удвоить бонусные очки, если смогу! –

+0

Я просто все понял, было несколько концептуальных ошибок. Поэтому нет необходимости проходить через пример. Однако я очень хочу поблагодарить вас за это время. Это было не то, что я искал, но то, что вы предлагали, определенно было типом помощи, которая была бы здоровой, если бы она была на мишени :) –

0

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

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