【发布时间】:2017-03-07 15:43:43
【问题描述】:
我正在使用 ssl(自签名证书)运行 Netty 4.2 套接字通信代码。
我的问题: 当客户端尝试使用 SSL 连接到服务器时,服务器会立即断开连接。服务器立即触发 channelUnregistered() 方法。
我注意到的一点是,一旦服务器启动,客户端连接第一次保持并正常工作。但是当客户端断开连接并尝试再次连接到服务器时,它会立即断开连接。
但如果没有 SSL,它可以正常工作,没有任何问题。
客户代码:
public Channel initializeNettySocket()
{
group = new NioEventLoopGroup();
try
{
ClientAdapterInitializer clientAdapterInitializer = null;
if (ServerSettings.isUseSSL())
{
// SSLEngine engine = SSLContextFactory.getClientContext().createSSLEngine();
SSLEngine engine = SSLContext.getDefault().createSSLEngine(host,port);
engine.setUseClientMode(true);
clientAdapterInitializer = new ClientAdapterInitializer(engine);
}
else
{
clientAdapterInitializer = new ClientAdapterInitializer();
}
Bootstrap bootstrap = new Bootstrap().group(group).channel(NioSocketChannel.class).handler(clientAdapterInitializer);
channel = bootstrap.connect(host,port).sync().channel();
Thread.sleep(3000);
setChannel(channel);
}
catch (Exception e)
{
System.out.println(e.getMessage());
e.printStackTrace();
}
return channel;
}
public class ClientAdapterInitializer extends ChannelInitializer<SocketChannel>
{
private SSLEngine sslCtx = null;
public ClientAdapterInitializer(SSLEngine sslCtx)
{
this.sslCtx = sslCtx;
}
public ClientAdapterInitializer()
{
}
@Override
protected void initChannel(SocketChannel channel) throws Exception
{
ChannelPipeline pipeline = channel.pipeline();
if (ServerSettings.isUseSSL())
{
// Add SSL handler first to encrypt and decrypt everything.
// In this example, we use a bogus certificate in the server side
// and accept any invalid certificates in the client side.
// You will need something more complicated to identify both
// and server in the real world.
//pipeline.addLast(sslCtx.newHandler(ch.alloc(), SecureChatClient.HOST, SecureChatClient.PORT));
pipeline.addLast(new SslHandler(sslCtx));
}
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("handler", new ClientAdapterHandler());
}
服务器端代码
public class ServerAdapterInitializer extends ChannelInitializer<SocketChannel>
{
private SSLEngine sslEngine;
public ServerAdapterInitializer(SSLEngine sslEngine)
{
this.sslEngine = sslEngine;
}
public ServerAdapterInitializer()
{
}
@Override
protected void initChannel(SocketChannel channel) throws Exception
{
ChannelPipeline pipeline = channel.pipeline();
if (sslEngine != null)
{
pipeline.addLast(new SslHandler(sslEngine));
}
Listeners.getInstance().getAllListeners().size();
RTReceiverAdapterHandler rtReceiverAdapterHandler = new RTReceiverAdapterHandler();
pipeline.addLast("idleStateHandler", new IdleStateHandler(0, 0, 10)); // add
// with
// name
pipeline.addLast("decoder", new MyStringDecoder(rtReceiverAdapterHandler));
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("handler", rtReceiverAdapterHandler);
}
}
public class RTReceiverAdapterHandler extends ChannelInboundHandlerAdapter
{
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception
{
if (ServerSettings.isUseSSL())
{
// Once session is secured, send a greeting and register the channel
// to the global channel
// list so the channel received the messages from others.
ctx.pipeline().get(SslHandler.class).handshakeFuture().addListener(new GenericFutureListener<Future<Channel>>()
{
@Override
public void operationComplete(Future<Channel> future) throws Exception
{
ctx.writeAndFlush("Welcome!\n");
ctx.writeAndFlush("Your session is protected by " + ctx.pipeline().get(SslHandler.class).engine().getSession().getCipherSuite()
+ " cipher suite.\n");
channels.add(ctx.channel());
}
});
}
else
{
super.channelActive(ctx);
}
}
}
【问题讨论】:
-
您可以尝试使用以下选项记录调试: System.setProperty("javax.net.debug", "ssl"); System.setProperty("ssl.debug", "true");
-
好的,我试试这个
-
我已启用有效的协议和密码。我遇到的问题已经消失了。但是现在,服务器一旦与客户端连接等待几秒钟并关闭连接,在客户端我得到异常--> nioEventLoopGroup-2-1, fatal error: 80: Inbound closed before received peer's close_notify: possible truncation attack?
-
再更新一次,我可以使用 SSL 连接到服务器,但是当我尝试写入 (channel.writeAndFlush("something")) 时,它会关闭连接。
-
如果您可以将您的代码放在 Gist 或 GitHub 上的其他位置,我可以尝试重现并提供帮助。