我已经设置了一个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();
}
}