我已经解决了这个问题。您需要创建一个 SSLEngine 实例并将其添加到每个客户端请求的处理程序管道中。我通过在 channelConnected 事件中添加处理程序并在断开连接的通道中删除 ssl 处理程序来完成此操作。这确保每个连接的通道都将被添加新的。
下面是处理程序的代码。这是使用 SSL 支持进行持久套接字连接的正确方法吗?
package server;
import static org.jboss.netty.buffer.ChannelBuffers.dynamicBuffer;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.group.DefaultChannelGroup;
import org.jboss.netty.handler.ssl.SslHandler;
import ssl.SslContextFactory;
import ssl.SslKeyStore;
public class ServerHandler extends SimpleChannelHandler {
private static final String ECHORES = "0057081082200000000000000400000000000000070612201399966400301";
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
System.out.println("Inside ServerHandler.messageReceived");
ChannelBuffer buffer = (ChannelBuffer) e.getMessage();
ChannelBuffer temp = dynamicBuffer();
temp.writeBytes(buffer);
if (temp.readableBytes() >= 4) {
byte messageLen[] = new byte[4];
temp.readBytes(messageLen);
int len = Integer.parseInt(new String(messageLen));
System.out.println("Length of the message is : " + len);
if (temp.readableBytes() >= len) {
byte[] message = new byte[len];
temp.readBytes(message);
System.out.println("Input message is : " + new String(message));
Channel channel = e.getChannel();
buffer = ChannelBuffers.copiedBuffer(ECHORES.getBytes());
ChannelFuture future = channel.write(buffer);
future.addListener(ChannelFutureListener.CLOSE);
}
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
e.getCause().printStackTrace();
Channel channel = e.getChannel();
channel.close();
}
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
String file = "test.jks";
SSLContext sslCtx = SslContextFactory.getServerContext(new SslKeyStore(file));
final SSLEngine sslEngine =sslCtx.createSSLEngine();
sslEngine.setNeedClientAuth(false);
sslEngine.setUseClientMode(false);
final SslHandler sslHandler = new SslHandler(sslEngine);
ctx.getPipeline().addFirst("ssl", sslHandler);
ChannelFuture handshakeFuture = sslHandler.handshake();
handshakeFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
System.out.println("SSL/TLS session established");
System.out.println("Your session is protected by "+ sslHandler.getEngine().
getSession().getCipherSuite() + " cipher suite.\n");
} else {
future.getChannel().close();
}
}
});
}
@Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("Inside ServerHandler.channelDisconnected");
ctx.getPipeline().remove("ssl");
}
}
使用带有 ssl 的 netty 时出现以下异常。我的第一笔交易和握手都很顺利。如果我再次向服务器发送新消息,我会收到此异常。
“javax.net.ssl.SSLException:SSLEngine 正在关闭/关闭”
这里可能出了什么问题。如何保持已建立的 TLS/SSL 会话?这个错误发生在 org.jboss.netty.handler.ssl.SslHandler.handshake(SslHandler.java:358)。
目的是让服务器使用持久的 TLS 套接字连接运行,以便客户端可以发送消息。
-TK