我有一个 netty 客户端等待等待服务器发送一些东西。这似乎在 3.7 版中运行良好。我试图将它迁移到 4.0,但我不断收到异常:
javax.net.ssl.SSLException:握手超时 nioEventLoopGroup-2-1,调用 closeOutbound() nioEventLoopGroup-2-1, closeOutboundInternal() nioEventLoopGroup-2-1,发送 TLSv1 ALERT:警告,描述 = close_notify nioEventLoopGroup-2-1,写入:TLSv1 警报,长度 = 2 nioEventLoopGroup-2-1,调用 closeInbound() nioEventLoopGroup-2-1,致命错误:80:入站在收到对等方的 close_notify 之前关闭:可能的截断攻击? javax.net.ssl.SSLException:入站在收到对等方的 close_notify 之前关闭:可能的截断攻击? nioEventLoopGroup-2-1,发送 TLSv1 ALERT:致命,描述 = internal_error nioEventLoopGroup-2-1,异常发送警报:java.io.IOException:写入端已关闭。
我在 3.7 netty 版本中有这段代码:
public class CtraderClient {
private final String host;
private final int port;
Channel channel = null;
public CtraderClient(String host, int port) {
this.host = host;
this.port = port;
}
public void run() {
// Configure the client.
ClientBootstrap bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
bootstrap.setOption("keepAlive", true);
HashedWheelTimer timer = new HashedWheelTimer();
// Configure the pipeline factory.
bootstrap.setPipelineFactory(new SecurePipelineFactory(timer));
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host,
port));
// Wait until the connection attempt succeeds or fails.
channel = future.awaitUninterruptibly().getChannel();
if (!future.isSuccess()) {
future.getCause().printStackTrace();
bootstrap.releaseExternalResources();
return;
}
}
}
public class SecurePipelineFactory implements ChannelPipelineFactory {
private final ChannelHandler idleStateHandler;
private Timer timer;
public SecurePipelineFactory(Timer timer) {
this.timer = timer;
this.idleStateHandler = new IdleStateHandler(timer, 0, 20, 0); // timer must be shared.
}
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = pipeline();
SSLContext sslcontext = SSLContext.getInstance("SSL");
sslcontext.init(null, null, null);
SSLEngine engine = sslcontext.createSSLEngine();
engine.setUseClientMode(true);
SslHandler sslHandler = new SslHandler(engine);
pipeline.addLast("ssl", sslHandler);
pipeline.addLast(
"frameDecoder",
new LengthFieldBasedFrameDecoder(
1048576, 0, 4, 0, 4));
pipeline.addLast("protobufDecoder",
new ProtobufDecoder(
ProtoMessage.getDefaultInstance()));
pipeline.addLast("frameEncoder",
new LengthFieldPrepender(4));
pipeline.addLast("protobufEncoder",
new ProtobufEncoder());
// pipeline.addLast("handler", new SecureHandler());
pipeline.addLast("protoHandler", new ProtoMessageHandler());
pipeline.addLast("idleStateHandler", idleStateHandler);
pipeline.addLast("heartHandler", new HeartbeatHandler());
return pipeline;
}
我已经改成这个以适应 4.0 版本:
public class CtraderClient {
private final String host;
private final int port;
Channel channel = null;
private static final Logger LOGGER = LoggerFactory
.getLogger(CtraderClient.class);
public CtraderClient(String host, int port) {
this.host = host;
this.port = port;
}
public void run() throws InterruptedException {
// Configure the client.
EventLoopGroup group = new NioEventLoopGroup();
Bootstrap b = new Bootstrap();
b.group(group);
b.channel(NioSocketChannel.class);
b.option(ChannelOption.SO_KEEPALIVE, true);
b.handler(new MyChannelInitializer ());
// Start the connection attempt.
ChannelFuture future = b.connect(new InetSocketAddress(host, port))
.sync();
channel = future.awaitUninterruptibly().channel();
if (!future.isSuccess()) {
future.cause().printStackTrace();
//bootstrap.releaseExternalResources();
return;
}
}
}
public class MyChannelInitializer extends ChannelInitializer {
private static final String PROTOCOL = "SSL";
@Override
public void initChannel(SocketChannel channel) throws Exception {
SslHandler sslHandler = createSSLHandler();
channel.pipeline().addLast("ssl", sslHandler);
channel.pipeline().addLast(
"frameDecoder",
new LengthFieldBasedFrameDecoder(
1048576, 0, 4, 0, 4));
channel.pipeline().addLast("protobufDecoder",
new ProtobufDecoder(
ProtoMessage.getDefaultInstance()));
channel.pipeline().addLast("frameEncoder",
new LengthFieldPrepender(4));
channel.pipeline().addLast("protobufEncoder",
new ProtobufEncoder());
channel.pipeline().addLast("protoHandler", new ProtoMessageHandler());
channel.pipeline().addLast("idleStateHandler", new IdleStateHandler(0, 20, 0));
channel.pipeline().addLast("heartHandler", new HeartbeatHandler());
}
private SslHandler createSSLHandler() throws NoSuchAlgorithmException,
KeyManagementException {
SSLEngine engine = createSSLEngine();
engine.setUseClientMode(true);
SslHandler sslHandler = new SslHandler(engine);
return sslHandler;
}
private SSLEngine createSSLEngine() throws NoSuchAlgorithmException,
KeyManagementException {
SSLContext sslcontext = SSLContext.getInstance(PROTOCOL);
sslcontext.init(null, null, null); //SecureTrustManagerFactory.getTrustManagers() --- I tried it with a dummy
// x09Trustmanager that returns new X509Certificate[0] in getAcceptedIssuers(),
//but I get the same exception
SSLEngine engine = sslcontext.createSSLEngine();
return engine;
}
}
有没有人知道我做错了什么?提前谢谢!