本博客 貓叔的博客,轉載請申明出處html
閱讀本文約 「4分鐘」java
適讀人羣:Java-Netty 初級git
版本:netty 4.1.*github
申明:本文旨在從新分享討論Netty官方相關案例,添加部分我的理解與要點解析。api
這個是InChat的案例地址,裏面補充了詳細的註釋,比起官方會容易看一點。數組
官方案例地址:netty.io/4.1/xref/io…安全
官方介紹:netty.io/4.1/api/io/…架構
公共抽象類,安全套接字協議實現充當工廠SSLEngine和SslHandler。在內部,它經過JDK SSLContext或OpenSSL 實現SSL_CTX,還有關於它的使用方式,若是你須要ssl加密的話ide
官方介紹:netty.io/4.1/api/io/…oop
用於配置新SslContext以進行建立的構建器,其中包含多個方法這裏就很少補充,你們能夠去看看
在TrustManagerFactory沒有任何驗證的狀況下信任全部X.509證書的不安全因素
注意:切勿TrustManagerFactory在生產中使用它。它純粹是出於測試目的,所以很是不安全。
生成臨時自簽名證書以進行測試
注意:切勿在生產中使用此類生成的證書和私鑰。它純粹是出於測試目的,所以很是不安全。它甚至使用不安全的僞隨機生成器在內部更快地生成
/** * @ClassName EchoClient * @Description 一個簡單的應答通信的實例 * @Author MySelf * @Date 2019/8/17 17:56 * @Version 1.0 **/
public final class EchoClient {
//判斷是否加密
static final boolean SSL = System.getProperty("ssl") != null;
//監聽本地服務
static final String HOST = System.getProperty("host", "127.0.0.1");
//監聽端口
static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
//發送消息的大小,用於EchoClientHandler
static final int SIZE = Integer.parseInt(System.getProperty("size", "256"));
public static void main(String[] args) throws Exception {
//公共抽象類,安全套接字協議實現充當工廠SSLEngine和SslHandler。在內部,它經過JDK SSLContext或OpenSSL 實現SSL_CTX
final SslContext sslCtx;
if (SSL){
//用於配置新SslContext以進行建立的構建器
sslCtx = SslContextBuilder.forClient()
//用於驗證遠程端點證書的可信管理器
//InsecureTrustManagerFactory:在TrustManagerFactory沒有任何驗證的狀況下信任全部X.509證書的不安全因素
//注:切勿TrustManagerFactory在生產中使用它。它純粹是出於測試目的,所以很是不安全。
.trustManager(InsecureTrustManagerFactory.INSTANCE).build();
}else {
sslCtx = null;
}
//事件循環
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY,true)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel sc) throws Exception {
ChannelPipeline p = sc.pipeline();
//瞭解SslContext的用法
if (sslCtx != null){
p.addLast(sslCtx.newHandler(sc.alloc(),HOST,PORT));
}
p.addLast(new EchoClientHandler());
}
});
//這個sync後的代碼均會執行
ChannelFuture f = b.connect(HOST,PORT).sync();
System.out.println("before-----");
//這個sync後的代碼不會執行
f.channel().closeFuture().sync();
System.out.println("after-----");
}finally {
group.shutdownGracefully();
}
}
}
複製代碼
/** * @ClassName EchoClientHandler * @Description TODO * @Author MySelf * @Date 2019/8/17 18:06 * @Version 1.0 **/
public class EchoClientHandler extends ChannelInboundHandlerAdapter {
private final ByteBuf firstMessage;
public EchoClientHandler(){
//獲取EchoClient的SIZE
//Unpooled:ByteBuf經過分配新空間或經過包裝或複製現有字節數組,字節緩衝區和字符串來建立新的
firstMessage = Unpooled.buffer(EchoClient.SIZE);
for (int i = 0; i < firstMessage.capacity(); i++){
firstMessage.writeByte((byte)i);
}
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush(firstMessage);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ctx.write(msg);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
複製代碼
/** * @ClassName EchoServer * @Description 服務端 * @Author MySelf * @Date 2019/8/17 18:15 * @Version 1.0 **/
public final class EchoServer {
static final boolean SSL = System.getProperty("ssl") != null;
static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
public static void main(String[] args) throws Exception {
final SslContext sslCtx;
if (SSL){
//SelfSignedCertificate:生成臨時自簽名證書以進行測試
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
}else{
sslCtx = null;
}
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
final EchoServerHandler serverHandler = new EchoServerHandler();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup,workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG,100)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
if (sslCtx != null){
p.addLast(sslCtx.newHandler(ch.alloc()));
}
p.addLast(serverHandler);
}
});
ChannelFuture f = b.bind(PORT).sync();
f.channel().closeFuture().sync();
}finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
複製代碼
/** * @ClassName EchoServerHandler * @Description TODO * @Author MySelf * @Date 2019/8/17 18:14 * @Version 1.0 **/
@ChannelHandler.Sharable
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ctx.write(msg);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
複製代碼
學習交流羣:728698035
現架構設計(碼農)兼創業技術顧問,不羈平庸,熱愛開源,雜談程序人生與不按期乾貨。