Вопрос по java – Netty другой конвейер для UDP датаграммы

2

У нас есть сервер, который уже реализован в TCP / IP, но теперь у нас есть требование, чтобы протокол также поддерживал UDP.

Каждая отправленная дейтаграмма UDP содержит все, что мне нужно для декодирования, поэтому это очень простая система ответов и ответов с данными в дейтаграмме, разделенными переносами строк.

Код для начальной загрузки при запуске сервера показан ниже:

    //SETUP UDP SERVER
    DatagramChannelFactory udpFactory = new NioDatagramChannelFactory(Executors.newCachedThreadPool());

    ConnectionlessBootstrap udpBootstrap = new ConnectionlessBootstrap(udpFactory);

    udpBootstrap.setOption("sendBufferSize", 65536);
    udpBootstrap.setOption("receiveBufferSize", 65536);
    udpBootstrap.setOption("receiveBufferSizePredictorFactory", new AdaptiveReceiveBufferSizePredictorFactory());

    udpBootstrap.setOption("broadcast", "true");
    udpBootstrap.setPipelineFactory(new ServerPipeLineFactoryUDP());
    udpBootstrap.bind(new InetSocketAddress(hostIp, 4000)); 

Код конвейера:

class ServerPipeLineFactoryUDP implements ChannelPipelineFactory
{

    private final static ExecutionHandler EXECUTION_HANDLER = new ExecutionHandler(new OrderedMemoryAwareThreadPoolExecutor(ScorpionFMS.THREAD_POOL_COUNT, 0, 0));

    public ServerPipeLineFactoryUDP()
    {

    }

    @Override
    public ChannelPipeline getPipeline() throws Exception
    {

    ChannelPipeline pipeline = pipeline();
    pipeline.addLast("debugup", new DebugUpstreamHandler("UDP"));
    pipeline.addLast("debugdown", new DebugDownstreamHandler("UDP"));

    pipeline.addLast("framer", new DelimiterBasedFrameDecoder(256, Delimiters.lineDelimiter()));

    pipeline.addLast("decoder", new UDPRequestDecoder(true));
    pipeline.addLast("encoder", new StringEncoder());
    pipeline.addLast("executor", EXECUTION_HANDLER);
    pipeline.addLast("handler", new UDPRequestHandler(

    return pipeline;
    }
}

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

Я знаю, что это ожидаемое поведение при чтении документации, но есть ли способ заставить netty воссоздать конвейер для каждой дейтаграммы? Или я иду по этому пути совершенно неправильно?

Короче говоря, я хочу, чтобы каждая датаграмма имела новый экземпляр конвейера (так же, как tcp)

Почему тыstore state в ваших обработчиках? Вам нужна концепция соединения для обмена сообщениями? Сначала кажется, что вам это не нужно, но позже вы, кажется, передумаете (зачем вам его хранить, если оно вам не нужно). , , MartinK

Ваш Ответ

2   ответа
0

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

к сожалению, проблема в том, что каналы не различаются по дейтаграмме, и это то, чего я пытаюсь достичь. Ciaran Fisher
5

Как я уже говорил в IRC, я думаю, что это может сделать то, что вы хотите, или, по крайней мере, дать вам некоторое представление.

public class Example {

    public static void main(String[] args) {
        final ChannelPipelineHandlerImpl perDatagramFactory = new ChannelPipelineHandlerImpl();

        DatagramChannelFactory udpFactory = new NioDatagramChannelFactory(Executors.newCachedThreadPool());

        ConnectionlessBootstrap udpBootstrap = new ConnectionlessBootstrap(udpFactory);

        udpBootstrap.setPipelineFactory(new ChannelPipelineFactory() {

            public ChannelPipeline getPipeline() throws Exception {
                return Channels.pipeline(new DistinctChannelPipelineHandler(perDatagramFactory));
            }
        });

    }

    private static final class DistinctChannelPipelineHandler implements ChannelDownstreamHandler, ChannelUpstreamHandler {
        private ChannelPipelineFactory factory;

        public DistinctChannelPipelineHandler(ChannelPipelineFactory factory) {
            this.factory = factory;
        }

        public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
            ChannelPipeline pipeline = factory.getPipeline();
            pipeline.attach(ctx.getChannel(), ctx.getPipeline().getSink());
            pipeline.sendUpstream(e);

            ctx.sendUpstream(e);

        }

        public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
            ChannelPipeline pipeline = factory.getPipeline();
            pipeline.attach(ctx.getChannel(), ctx.getPipeline().getSink());
            pipeline.sendDownstream(e);

            ctx.sendDownstream(e);
        }

    }

    private static final class ChannelPipelineHandlerImpl implements ChannelPipelineFactory {

        public ChannelPipeline getPipeline() throws Exception {
            // Add your handlers here
            return Channels.pipeline();
        }

    }
}
Круто .. спасибо за отзыв!
@ NormanMaurer Есть ли похожий пример для этого в Netty 4? Нашел это очень полезно!
С несколькими изменениями это было именно то, что мне было нужно. еще раз спасибо! Теперь TCP / IP и UDP работают отлично. Ciaran Fisher

Похожие вопросы