Netty 快速入門
阿新 • • 發佈:2021-01-24
技術標籤:Netty學習
2.3 Netty快速入門
2.3.1 伺服器端
-
建立了bossGroup 和 workerGroup
-
觀察bootstrap.group(bossGroup, workerGroup)方法
可以看出bossGroup 是 parentGroup ,workerGroup 是 childGroup
- 給workerGroup初始化通道,然後向管道里面扔一個Handler
//建立BossGroup 和 WorkerGroup,都是無限迴圈
//子執行緒NioEventLoop的默認個數是CPU核心數*2
EventLoopGroup bossGroup = new NioEventLoopGroup(1); //只處理連線請求
NioEventLoopGroup workerGroup = new NioEventLoopGroup(); //處理業務
try{
ServerBootstrap bootstrap = new ServerBootstrap(); //伺服器啟動物件
bootstrap.group(bossGroup, workerGroup) //兩個執行緒組
.channel(NioServerSocketChannel.class) //伺服器通道
.option(ChannelOption. SO_BACKLOG, 128) //執行緒佇列等待連線的個數
.childOption(ChannelOption.SO_KEEPALIVE, true) //保持活動連線狀態
.childHandler(new ChannelInitializer<SocketChannel>() { //建立一個通道初始化物件
//給pipeline設定處理器
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new NettyServerHandler());
}
}); //給workerGroup 的 EventLoop設定處理器
System.out.println("server is ready");
ChannelFuture cf = bootstrap.bind(6668).sync(); //繫結埠並且同步,就是啟動伺服器
cf.channel().closeFuture().sync(); //對關閉通道進行監聽
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
-
Handler程式碼
Handler繼承了
ChannelInboundHandlerAdapter
-
並且複寫的是生命週期函式
- channelRead – 讀取客戶端傳送的訊息
- channelReadComplete – 資料讀取完畢
- exceptionCaught – 發生異常
-
其中的ctx有很多東西
-
msg可以轉成ByteBuf,這是Netty提供的一個東西
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
//讀取客戶端傳送的訊息
/*
* ctx中有
* 管道:Handler處理
* 通道:資料處理
* 地址
* msg就是客戶端傳送的資料
* */
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// super.channelRead(ctx, msg);
System.out.println("Server ctx = " + ctx);
ByteBuf buf = (ByteBuf) msg;
Channel channel = ctx.channel();
System.out.println("客戶端傳送的訊息是:" + buf.toString(CharsetUtil.UTF_8));
System.out.println("客戶端地址:" + channel.remoteAddress());
}
//資料讀取完畢
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// super.channelReadComplete(ctx);
ctx.writeAndFlush(Unpooled.copiedBuffer("Hello,客戶端",CharsetUtil.UTF_8)); //寫入緩衝並重新整理
}
//發生異常
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
//super.exceptionCaught(ctx, cause);
ctx.close();
}
}
2.3.2 伺服器端
-
客戶端這裡設定相對較少
其中不同的是它的操作是連線客戶端
ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 6668).sync();
//事件迴圈組
NioEventLoopGroup eventExecutors = new NioEventLoopGroup();
try{
//客戶端啟動物件
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventExecutors) //設定執行緒組
.channel(NioSocketChannel.class) //客戶端通道
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new NettyClientHandler()); //加入Handler
}
});
System.out.println("Client is Ready");
//啟動客戶端連線伺服器端
ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 6668).sync();
channelFuture.channel().closeFuture().sync();
} finally {
eventExecutors.shutdownGracefully();
}
- 來看Handler,依舊是複寫生命週期函式
public class NettyClientHandler extends ChannelInboundHandlerAdapter {
//通道就緒
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// super.channelActive(ctx);
System.out.println("Client " + ctx);
ctx.writeAndFlush(Unpooled.copiedBuffer("Hello Server: 淦", CharsetUtil.UTF_8));
}
//通道有讀取事件時
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//super.channelRead(ctx, msg);
ByteBuf buf = (ByteBuf)msg;
System.out.println("伺服器傳送回覆的訊息: " + buf.toString(CharsetUtil.UTF_8));
System.out.println("伺服器的地址:" + ctx.channel().remoteAddress());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// super.exceptionCaught(ctx, cause);
cause.printStackTrace();
ctx.close();
}
}