使用ssl时,在channelRead0之前调用channelReadComplete

时间:2015-03-28 14:15:40

标签: netty

我已经设置了一个junit测试,首先启动服务器,然后连接客户端。响应应该回来了。然后我添加ssl并且响应仍然返回到客户端,但由于某种原因,似乎在channelRead0之前调用channelReadComplete方法两次。可以很容易地避免在尝试使用fireChannelRead(msg)中继到下一个处理程序的null对象上创建的异常,只需在调用fireChannelRead(msg)之前测试null,但是如果有什么我可以做到避免这种行为请赐教。 ssl处理程序的设置与Telnet示例类似。我正在使用4.0.25.Final。

以下是服务器的ssl代码:

ChannelPipeline cp = ch.pipeline();
SelfSignedCertificate cert = new SelfSignedCertificate();
SslContext cont = SslContext.newServerContext(
cert.certificate(), cert.privateKey());
cp.addLast("ssl", cont.newHandler(ch.alloc()));

和客户:

ChannelPipeline pipeline = ch.pipeline();
SslContext cont = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE);
pipeline.addLast(cont.newHandler(ch.alloc(),HOST, SERVER_SECURE_PORT));

这是JUnit测试:

public class MySSLTest {
    private static Logger utilLogger = Logger.getLogger("my.logger.clientside");
    private static EventLoopGroup bossGroup;
    private static EventLoopGroup workerGroup;
    private static final int SERVER_SECURE_PORT = 5061;
    private static final int CLIENT_PORT = 5062;
    private static final String HOST = "localhost";

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        utilLogger.info("starting up");
        try {

            ServerBootstrap b = new ServerBootstrap();
            bossGroup = new NioEventLoopGroup(1);
            workerGroup = new NioEventLoopGroup();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.DEBUG))
                    .childHandler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel ch)
                                throws Exception {
                            ChannelPipeline cp = ch.pipeline();
                            SelfSignedCertificate cert = new SelfSignedCertificate();
                            SslContext cont = SslContext.newServerContext(
                                    cert.certificate(), cert.privateKey());
                            cp.addLast("ssl", cont.newHandler(ch.alloc()));
                            cp.addLast(
                                    "inhandler",
                                    new MySimpleChannelInboundTcpHandlerServer());

                        }
                    });

            // b.bind(SERVER_SECURE_PORT).sync().channel().closeFuture().sync();
            b.bind(SERVER_SECURE_PORT).sync();

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {

        }
    }

    @AfterClass
    public static void takedownAfterClass() {

        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }

    @Test
    public void testSendAndReceivePacket() {
        EventLoopGroup group = null;
        utilLogger.info("Test");
        try {
            Bootstrap b = new Bootstrap();
            group = new NioEventLoopGroup();
            b.group(group).channel(NioSocketChannel.class)
                    .option(ChannelOption.IP_TOS, 24)
                    .handler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel ch)
                                throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            SslContext cont = SslContext
                                    .newClientContext(InsecureTrustManagerFactory.INSTANCE);
                            pipeline.addLast(cont.newHandler(ch.alloc(), HOST,
                                    SERVER_SECURE_PORT));
                            pipeline.addLast(new MySimpleChannelInboundTcpHandlerBugReport());

                        }
                    });
            Channel ch = null;
            InetSocketAddress ria = new InetSocketAddress(HOST,
                    SERVER_SECURE_PORT);
            InetSocketAddress lia = new InetSocketAddress(HOST, CLIENT_PORT);
            try {
                utilLogger.info("connecting");
                ch = b.connect(ria, lia).sync().channel();
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (ch != null) {
                utilLogger.info("sending request");

                ChannelFuture wcf = null;
                ByteBuf bb = null;
                bb = Unpooled.copiedBuffer("REGISTER", CharsetUtil.UTF_8);

                wcf = ch.write(bb);
                ch.flush();
                utilLogger.info("request sent");
                if (!wcf.await(600)) {
                    utilLogger.info("request not written");
                    ch.close();
                }
                if (!ch.closeFuture().await(1000))
                    utilLogger.info("not closed within 1000ms");

            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (Throwable e) {
            e.printStackTrace();
        } finally {
            group.shutdownGracefully();
        }
        assertTrue(MySimpleChannelInboundTcpHandlerBugReport.TEST_SUCCEDED);
    }

}

这是服务器处理程序:

public class MySimpleChannelInboundTcpHandlerServer extends
        SimpleChannelInboundHandler<ByteBuf> {
    private Logger utilLogger = Logger.getLogger("my.logger.serverside");

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf bb)
            throws Exception {
        utilLogger.info("channelRead0");
        String response = bb.toString(CharsetUtil.UTF_8);
        ByteBuf bbOut = Unpooled.copiedBuffer(response, CharsetUtil.UTF_8);
        ctx.write(bbOut);
        ctx.flush();

    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        super.channelReadComplete(ctx);
        utilLogger.info("channelReadComplete");

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

}

客户端处理程序:

public class MySimpleChannelInboundTcpHandlerBugReport extends
        SimpleChannelInboundHandler<ByteBuf> {
    public static boolean TEST_SUCCEDED = false;
    private Logger utilLogger = Logger.getLogger("my.logger.clientside");

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf bb)
            throws Exception {
        String response = bb.toString(CharsetUtil.UTF_8);
        utilLogger.info("response: " + response);
        if (response.startsWith("REGISTER")) {
            TEST_SUCCEDED = true;
            ctx.close();
        }

    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        super.channelReadComplete(ctx);

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

}

0 个答案:

没有答案