二. 学习Netty之ChannelHandlerContext

ChannelHandlerContext可以确保一个ChannelHandler和它的pipeline和其他的handler联系起来

  1. handler可以通知pipeline里的下一个handler
  2. handler可以动态的修改它的pipeline在运行时

通知: ChannelHandler可以通知同一个ChannelPipeline 中的下一个Handler 修改 pipeline() 通过这个方法,handler可以修改同一个ChannelPipeline最近的一个 handler

保存上下文,以后需要的时候再用

public class MyHandler extends ChannelHandlerAdapter {
  
       private ChannelHandlerContext ctx;
  
       public void beforeAdd(ChannelHandlerContext ctx) {
           this.ctx = ctx;
       }
  
       public void login(String username, password) {
           ctx.write(new LoginMessage(username, password));
       }
       ...
   }

3.存储状态类的信息 attr(AttributeKey)

4.一个handler可以有不止一个的context 一个handler可以被添加到多个pipeline,也可以被一个pipeline添加多次

public class FactorialHandler extends ChannelHandlerAdapter {
  
     private final AttributeKey<Integer> counter = AttributeKey.valueOf("counter");
  
     // This handler will receive a sequence of increasing integers starting
     // from 1.
      @Override
     public void channelRead(ChannelHandlerContext ctx, Object msg) {
       Attribute<Integer> attr = ctx.getAttr(counter);
       Integer a = ctx.getAttr(counter).get();
  
       if (a == null) {
         a = 1;
       }
  
       attr.set(a * (Integer) msg);
     }
   }
  
   // Different context objects are given to "f1", "f2", "f3", and "f4" even if
   // they refer to the same handler instance.  Because the FactorialHandler
   // stores its state in a context object (using an AttributeKey), the factorial is
   // calculated correctly 4 times once the two pipelines (p1 and p2) are active.
   FactorialHandler fh = new FactorialHandler();
  
   ChannelPipeline p1 = Channels.pipeline();
   p1.addLast("f1", fh);
   p1.addLast("f2", fh);
  
   ChannelPipeline p2 = Channels.pipeline();
   p2.addLast("f3", fh);
   p2.addLast("f4", fh);
   

注意: 每个channel都有一个pipeline 每个handler都有一个context

[attr相当于就是session.一开始我有疑惑,每个handler都有一个context, 那么context.attr() 相当于每个handler的attr都不一样了,怎么会像是session的功能呢? 原来,attr是附着在channel上的,而不是context上.context.attr实际上调用的还是channel.attr] ** 上面的理解是错误的,不应该吧attr类比为session. 通常,我们怎么标识客户端呢?一个ip+port ,放在全局的map里作为key.那么这个map才相当于session 而attr要理解为附件,这个附近可以是哪些东西呢,比如一个auth串, 权限验证的东西, 加密的东西等等.**

一个bossGroup是一个线程组,在bind的时候创建ServerChannel,也就意味着即使这是一个线程组, 那么只绑定一个端口的时候,那么也只有一条线程accept用户的接入请求。

handler() childHandler()

handler() 里的handler是在bossGroup里执行的,也就是说当只绑定一个端口的时候,这个handler是和accept在一个线程中的。而childHandler里的handler则是在workerGroup里执行的

转载于:https://my.oschina.net/u/1777377/blog/524230

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的 Netty Bootstrap 学习例子,写在 main 方法: ```java import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; public class NettyClient { private final String host; private final int port; public NettyClient(String host, int port) { this.host = host; this.port = port; } public void run() throws InterruptedException { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new NettyClientHandler()); } }); ChannelFuture future = bootstrap.connect(host, port).sync(); future.channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } public static void main(String[] args) throws InterruptedException { String host = "localhost"; int port = 8888; new NettyClient(host, port).run(); } } class NettyClientHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { String msg = "Hello, Netty!"; ByteBuf byteBuf = Unpooled.buffer(msg.getBytes().length); byteBuf.writeBytes(msg.getBytes()); ctx.writeAndFlush(byteBuf); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf byteBuf = (ByteBuf) msg; byte[] bytes = new byte[byteBuf.readableBytes()]; byteBuf.readBytes(bytes); String result = new String(bytes); System.out.println("Received message from server: " + result); byteBuf.release(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } } ``` 这是一个简单的 Netty 客户端,它会连接到指定的服务器地址和端口,并向服务器发送一条消息,然后等待服务器的响应。在这个例子,我们使用了 NioEventLoopGroup 和 NioSocketChannel,具体细节可以参考 Netty 官方文档。同时,我们也实现了一个 NettyClientHandler,它会在客户端与服务器建立连接后被调用,并且会在接收到服务器的响应后被调用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值