Grizzly 2.2 目前可用的文档很少,超出示例代码中存在的文档,我发现这与 SSL 实现有关,因此最难导航。我迫切需要这方面的一些指导。在查看了我的代码以确定我需要发布什么才能提出一个完整的问题后,我意识到首先巩固基础知识可能是最有益的。
下面是Grizzly 项目提供的三个类,用于演示 Grizzly 的 SSL 功能的示例实现。除了删除注释之外,该代码与git://java.net/grizzly~git中维护的 2.2.19 发布的代码库相同,也可在此处获得。
git 存储库还提供了引用的信任库和密钥库。
回声过滤器:
public class EchoFilter extends BaseFilter{
@Override
public NextAction handleRead(FilterChainContext ctx)throws IOException {
//|Peer address is used for non-connected UDP Connection
final Object peerAddress = ctx.getAddress();
final Object message = ctx.getMessage();
ctx.write(peerAddress, message, null);
return ctx.getStopAction();
}
}
SSLEcho服务器:
public class SSLEchoServer{
public static final String HOST = "localhost";
public static final int PORT = 7777;
public static void main(String[] args) throws IOException{
//|Create a FilterChain using FilterChainBuilder
FilterChainBuilder filterChainBuilder = FilterChainBuilder.stateless();
//|Add TransportFilter, which is responsible for reading and writing data to the connection
filterChainBuilder.add(new TransportFilter());
//|Initialize and add SSLFilter
final SSLEngineConfigurator serverConfig = initializeSSL();
final SSLEngineConfigurator clientConfig = serverConfig.copy().setClientMode(true);
filterChainBuilder.add(new SSLFilter(serverConfig, clientConfig));
//|Add StringFilter, which will be responsible for Buffer <-> String transformation
filterChainBuilder.add(new StringFilter(Charset.forName("UTF-8")));
//|Use the plain EchoFilter
filterChainBuilder.add(new EchoFilter());
//|Create TCP transport
final TCPNIOTransport transport = TCPNIOTransportBuilder.newInstance().build();
//|Set filterchain as a Transport Processor
transport.setProcessor(filterChainBuilder.build());
try{
//|Binding transport to start listen on certain host and port
transport.bind(HOST, PORT);
//|Start the transport
transport.start();
System.out.println("Press any key to stop the server...");
System.in.read();
}finally{
System.out.println("Stopping transport...");
//|Stop the transport
transport.stop();
System.out.println("Stopped transport...");
}
}
private static SSLEngineConfigurator initializeSSL(){
//|Initialize SSLContext configuration
SSLContextConfigurator sslContextConfig = new SSLContextConfigurator();
//|Set key store
ClassLoader cl = SSLEchoServer.class.getClassLoader();
URL cacertsUrl = cl.getResource("ssltest-cacerts.jks");
if(cacertsUrl != null){
sslContextConfig.setTrustStoreFile(cacertsUrl.getFile());
sslContextConfig.setTrustStorePass("changeit");
}
//|Set trust store
URL keystoreUrl = cl.getResource("ssltest-keystore.jks");
if(keystoreUrl != null){
sslContextConfig.setKeyStoreFile(keystoreUrl.getFile());
sslContextConfig.setKeyStorePass("changeit");
}
//|Create SSLEngine configurator
return new SSLEngineConfigurator(sslContextConfig.createSSLContext(), false, false, false);
}
}
SSLEcho客户端:
public class SSLEchoClient{
private static final String MESSAGE = "Hello World!";
public static void main(String[] args) throws IOException{
//|Create a FilterChain using FilterChainBuilder
FilterChainBuilder filterChainBuilder = FilterChainBuilder.stateless();
//|Add TransportFilter, which is responsible for reading and writing data to the connection
filterChainBuilder.add(new TransportFilter());
//|Initialize and add SSLFilter
final SSLEngineConfigurator serverConfig = initializeSSL();
final SSLEngineConfigurator clientConfig = serverConfig.copy().setClientMode(true);
final SSLFilter sslFilter = new SSLFilter(serverConfig, clientConfig);
filterChainBuilder.add(sslFilter);
//|Add StringFilter, which will be responsible for Buffer <-> String transformation
filterChainBuilder.add(new StringFilter(Charset.forName("UTF-8")));
//|Add Filter, which will send a greeting message and check the result
filterChainBuilder.add(new SendMessageFilter(sslFilter));
//|Create TCP transport
final TCPNIOTransport transport = TCPNIOTransportBuilder.newInstance().build();
//|Set filterchain as a Transport Processor
transport.setProcessor(filterChainBuilder.build());
try{
//|Start the transport
transport.start();
//|Perform async. connect to the server
transport.connect(SSLEchoServer.HOST, SSLEchoServer.PORT);
System.out.println("Press any key to stop the client...");
System.in.read();
}finally{
System.out.println("Stopping transport...");
//|Stop the transport
transport.stop();
System.out.println("Stopped transport...");
}
}
private static class SendMessageFilter extends BaseFilter{
private final SSLFilter sslFilter;
public SendMessageFilter(SSLFilter sslFilter){
this.sslFilter = sslFilter;
}
@Override
@SuppressWarnings("unchecked")
public NextAction handleConnect(FilterChainContext ctx) throws IOException{
final Connection connection = ctx.getConnection();
//|Execute async SSL handshake
sslFilter.handshake(connection, new EmptyCompletionHandler<SSLEngine>(){
//|Once SSL handshake will be completed - send greeting message
@Override
public void completed(SSLEngine result){
//|Here we send String directly
connection.write(MESSAGE);
}
});
return ctx.getInvokeAction();
}
@Override
public NextAction handleRead(FilterChainContext ctx) throws IOException{
//|The received message is String
final String message = (String) ctx.getMessage();
//|Check the message
if(MESSAGE.equals(message)){
System.out.println("Got echo message: \"" + message + "\"");
}else{
System.out.println("Got unexpected echo message: \"" + message + "\"");
}
return ctx.getStopAction();
}
}
private static SSLEngineConfigurator initializeSSL(){
//|Initialize SSLContext configuration
SSLContextConfigurator sslContextConfig = new SSLContextConfigurator();
//|Set key store
ClassLoader cl = SSLEchoClient.class.getClassLoader();
URL cacertsUrl = cl.getResource("ssltest-cacerts.jks");
if(cacertsUrl != null){
sslContextConfig.setTrustStoreFile(cacertsUrl.getFile());
sslContextConfig.setTrustStorePass("changeit");
}
//|Set trust store
URL keystoreUrl = cl.getResource("ssltest-keystore.jks");
if(keystoreUrl != null){
sslContextConfig.setKeyStoreFile(keystoreUrl.getFile());
sslContextConfig.setKeyStorePass("changeit");
}
//|Create SSLEngine configurator
return new SSLEngineConfigurator(sslContextConfig.createSSLContext(), false, false, false);
}
}
执行时:
运行 SSLEchoServer:
按任意键停止服务器...
运行 SSLEchoClient:
按任意键停止客户端...
问题:
这段代码应该完成或演示什么?除了您在上面看到的控制台输出之外,这段代码对我没有任何作用。
在查看代码时,我的期望是客户端应该启动其 TCP 传输并将其连接到服务器。在建立该连接的过程中,之前添加到过滤器流中的SendMessageFilter将执行其handleConnect()方法,我确认该方法确实执行了。但是,此代码从不执行connection.write(MESSAGE)语句。
很明显,这里的意图是在握手线程完成后执行write()方法,但似乎没有这样做,并且在检查grizzly-framework-2.2.19中 SSLFilter 类中的handshake()方法时,我甚至无法确定重写的父完成()方法的定义位置。
任何人都可以提供一些见解,这种断开是否是由于我对这里的某些内容缺乏理解,或者它是否可能是 Grizzly 提供的示例实现中的错误?我相信澄清这一点将大大促进我在这里的理解。先感谢您!