Netty 快速入门系列 - Chapter 2 Netty3.x 【第三讲】Hello

Chapter2 章节结构



1. Netty版本大致版本分为  netty3.x  和  netty4.x、netty5.x

2. 应用范围

1. 分布式进程通信
例如: hadoop、dubbo、akka等具有分布式功能的框架,底层RPC通信都是基于netty实现的,这些框架使用的版本通常都还在用netty3.x

2. 游戏服务器开发

最新的游戏服务器有部分公司可能已经开始采用netty4.x 或 netty5.x

3. Hello World案例


Server端 

a. HelloServer

package com.john.netty.learn.ch02_03.server;


import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelHandler;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;


public class HelloServer {


  public HelloServer(int port) {


     ServerBootstrap serverBootstrap = new ServerBootstrap();


     serverBootstrap.setFactory(new NioServerSocketChannelFactory(boss, workers));


     serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() {


       @Override
       public ChannelPipeline getPipeline() throws Exception {


          ChannelPipeline channelPipeline = Channels.pipeline();
          channelPipeline.addLast("Decoder", new StringDecoder());
          channelPipeline.addLast("HelloWorldHandler", new HelloChannelHandler());
          channelPipeline.addLast("Encoder", new StringEncoder());


          return channelPipeline;
       }
     });


     serverBootstrap.bind(new InetSocketAddress(port));
  }


  private ExecutorService boss = Executors.newCachedThreadPool();


  private ExecutorService workers = Executors.newCachedThreadPool();


  public static void main(String[] args) {


     new HelloServer(3000);
  }
}
 

b. HelloChannelHandler 

package com.john.netty.learn.ch02_03.server;


import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
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.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;


public class HelloChannelHandler extends SimpleChannelHandler {


  public HelloChannelHandler() {


  }


  /**
   * 接收到消息
   */
  @Override
  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {


     // 没有过滤器
     // ChannelBuffer channelBuffer = (ChannelBuffer) e.getMessage();
     // System.out.println("接收到消息:" + new String(channelBuffer.array()));


     // 回写数据
     // ctx.getChannel().write(ChannelBuffers.wrappedBuffer(("Hi " +
     // e.getMessage()).getBytes()));


     // channelPipeline.addLast("Decoder", new StringDecoder());
     System.out.println("接收到消息:" + e.getMessage());


     // channelPipeline.addLast("Encoder", new StringEncoder());
     ctx.getChannel().write("Hi " + e.getMessage());


  }


  @Override
  public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
     System.out.println("channelConnected");
     super.channelConnected(ctx, e);
  }


  /**
   * 建立Channel成功,关闭通道时候,才会触发Disconnect
   */
  @Override
  public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {


     System.out.println("channelDisconnected");


     super.channelDisconnected(ctx, e);
  }


  /**
   * Channel 关闭
   */
  @Override
  public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {


     System.out.println("channelClosed");


     super.channelClosed(ctx, e);
  }


  /**
   * 捕获异常
   */


  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
     e.getCause().printStackTrace();
     super.exceptionCaught(ctx, e);
  }
}

Client端 

a. HelloClient

package com.john.netty.learn.ch02_03.client;


import java.net.InetSocketAddress;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;


import com.john.netty.learn.ch02_03.server.HelloChannelHandler;


public class HelloClient {


  public HelloClient(String ip, int port) {


    ClientBootstrap clientBootstrap = new ClientBootstrap();


    clientBootstrap.setFactory(new NioClientSocketChannelFactory(boss, workers));


    clientBootstrap.setPipelineFactory(new ChannelPipelineFactory() {


      @Override
      public ChannelPipeline getPipeline() throws Exception {


        ChannelPipeline channelPipeline = Channels.pipeline();
        channelPipeline.addLast("Decoder", new StringDecoder());
        channelPipeline.addLast("HiHandler", new HiChannelHandler());
        channelPipeline.addLast("Encoder", new StringEncoder());


        return channelPipeline;
      }
    });


    ChannelFuture channelFuture = clientBootstrap.connect(new InetSocketAddress(ip, port));


    Channel channel = channelFuture.getChannel();


    System.out.println("client start");


    Scanner scanner = new Scanner(System.in);


    while (true) {


      System.out.println("Please input:");
      channel.write(scanner.nextLine());


    }


  }


  private ExecutorService boss = Executors.newSingleThreadExecutor();


  private ExecutorService workers = Executors.newCachedThreadPool();


  public static void main(String[] args) {


    new HelloClient("127.0.0.1", 3000);
  }


}

 

b.  HiChannelHandler

package com.john.netty.learn.ch02_03.client;


import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
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.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;


public class HiChannelHandler extends SimpleChannelHandler {


  public HiChannelHandler() {


  }


  /**
   * 接收到消息
   */
  @Override
  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {


     // 没有过滤器
     // ChannelBuffer channelBuffer = (ChannelBuffer) e.getMessage();
     // System.out.println("接收到消息:" + new String(channelBuffer.array()));


     // 回写数据
     // ctx.getChannel().write(ChannelBuffers.wrappedBuffer(("Hi " +
     // e.getMessage()).getBytes()));


     // channelPipeline.addLast("Decoder", new StringDecoder());
     System.out.println("接收到消息:" + e.getMessage());


     


  }


  @Override
  public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
     System.out.println("channelConnected");
     super.channelConnected(ctx, e);
  }


  /**
   * 建立Channel成功,关闭通道时候,才会触发Disconnect
   */
  @Override
  public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {


     System.out.println("channelDisconnected");


     super.channelDisconnected(ctx, e);
  }


  /**
   * Channel 关闭
   */
  @Override
  public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {


     System.out.println("channelClosed");


     super.channelClosed(ctx, e);
  }


  /**
   * 捕获异常
   */


  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
     e.getCause().printStackTrace();
     super.exceptionCaught(ctx, e);
  }
}

Netty hello world 讲解说明:

1、netty服务端hello world案例

   SimpleChannelHandler 处理消息接收和写
    messageReceived接收消息
    channelConnected新连接,通常用来检测IP是否是黑名单
     hannelDisconnected链接关闭,可以再用户断线的时候清楚用户的缓存数据等 


2、netty客户端hello world案例

    channelDisconnected与channelClosed的区别?
    channelDisconnected只有在连接建立后断开才会调用
    channelClosed无论连接是否成功都会调用关闭资源
 


服务端显示Received:Alice,但客户端报错C:\Users\admin\.jdks\jdk-17.0.12+7\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2024.3.6\lib\idea_rt.jar=52904" -Dfile.encoding=UTF-8 -classpath D:\UserData\Desktop\Netty和gRPC\Netty_TEST\target\classes;D:\r\io\netty\netty-all\4.1.86.Final\netty-all-4.1.86.Final.jar;D:\r\io\netty\netty-buffer\4.1.86.Final\netty-buffer-4.1.86.Final.jar;D:\r\io\netty\netty-codec\4.1.86.Final\netty-codec-4.1.86.Final.jar;D:\r\io\netty\netty-codec-dns\4.1.86.Final\netty-codec-dns-4.1.86.Final.jar;D:\r\io\netty\netty-codec-haproxy\4.1.86.Final\netty-codec-haproxy-4.1.86.Final.jar;D:\r\io\netty\netty-codec-http\4.1.86.Final\netty-codec-http-4.1.86.Final.jar;D:\r\io\netty\netty-codec-http2\4.1.86.Final\netty-codec-http2-4.1.86.Final.jar;D:\r\io\netty\netty-codec-memcache\4.1.86.Final\netty-codec-memcache-4.1.86.Final.jar;D:\r\io\netty\netty-codec-mqtt\4.1.86.Final\netty-codec-mqtt-4.1.86.Final.jar;D:\r\io\netty\netty-codec-redis\4.1.86.Final\netty-codec-redis-4.1.86.Final.jar;D:\r\io\netty\netty-codec-smtp\4.1.86.Final\netty-codec-smtp-4.1.86.Final.jar;D:\r\io\netty\netty-codec-socks\4.1.86.Final\netty-codec-socks-4.1.86.Final.jar;D:\r\io\netty\netty-codec-stomp\4.1.86.Final\netty-codec-stomp-4.1.86.Final.jar;D:\r\io\netty\netty-codec-xml\4.1.86.Final\netty-codec-xml-4.1.86.Final.jar;D:\r\io\netty\netty-common\4.1.86.Final\netty-common-4.1.86.Final.jar;D:\r\io\netty\netty-handler\4.1.86.Final\netty-handler-4.1.86.Final.jar;D:\r\io\netty\netty-transport-native-unix-common\4.1.86.Final\netty-transport-native-unix-common-4.1.86.Final.jar;D:\r\io\netty\netty-handler-proxy\4.1.86.Final\netty-handler-proxy-4.1.86.Final.jar;D:\r\io\netty\netty-handler-ssl-ocsp\4.1.86.Final\netty-handler-ssl-ocsp-4.1.86.Final.jar;D:\r\io\netty\netty-resolver\4.1.86.Final\netty-resolver-4.1.86.Final.jar;D:\r\io\netty\netty-resolver-dns\4.1.86.Final\netty-resolver-dns-4.1.86.Final.jar;D:\r\io\netty\netty-transport\4.1.86.Final\netty-transport-4.1.86.Final.jar;D:\r\io\netty\netty-transport-rxtx\4.1.86.Final\netty-transport-rxtx-4.1.86.Final.jar;D:\r\io\netty\netty-transport-sctp\4.1.86.Final\netty-transport-sctp-4.1.86.Final.jar;D:\r\io\netty\netty-transport-udt\4.1.86.Final\netty-transport-udt-4.1.86.Final.jar;D:\r\io\netty\netty-transport-classes-epoll\4.1.86.Final\netty-transport-classes-epoll-4.1.86.Final.jar;D:\r\io\netty\netty-transport-classes-kqueue\4.1.86.Final\netty-transport-classes-kqueue-4.1.86.Final.jar;D:\r\io\netty\netty-resolver-dns-classes-macos\4.1.86.Final\netty-resolver-dns-classes-macos-4.1.86.Final.jar;D:\r\io\netty\netty-transport-native-epoll\4.1.86.Final\netty-transport-native-epoll-4.1.86.Final-linux-x86_64.jar;D:\r\io\netty\netty-transport-native-epoll\4.1.86.Final\netty-transport-native-epoll-4.1.86.Final-linux-aarch_64.jar;D:\r\io\netty\netty-transport-native-kqueue\4.1.86.Final\netty-transport-native-kqueue-4.1.86.Final-osx-x86_64.jar;D:\r\io\netty\netty-transport-native-kqueue\4.1.86.Final\netty-transport-native-kqueue-4.1.86.Final-osx-aarch_64.jar;D:\r\io\netty\netty-resolver-dns-native-macos\4.1.86.Final\netty-resolver-dns-native-macos-4.1.86.Final-osx-x86_64.jar;D:\r\io\netty\netty-resolver-dns-native-macos\4.1.86.Final\netty-resolver-dns-native-macos-4.1.86.Final-osx-aarch_64.jar;D:\r\com\fasterxml\jackson\core\jackson-databind\2.13.0\jackson-databind-2.13.0.jar;D:\r\com\fasterxml\jackson\core\jackson-annotations\2.13.0\jackson-annotations-2.13.0.jar;D:\r\com\fasterxml\jackson\core\jackson-core\2.13.0\jackson-core-2.13.0.jar org.example.GreetClient 8月 25, 2025 5:31:34 下午 io.netty.channel.DefaultChannelPipeline onUnhandledInboundException 警告: An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception. com.fasterxml.jackson.core.JsonParseException: Illegal character ((CTRL-CHAR, code 0)): only regular white space (\r, \n, \t) is allowed between tokens at [Source: (String)"\u0000\u0000\u0000*{"name":"Alice","greeting":"Hello, Alice"}"; line: 1, column: 2] at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:2391) at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:735) at com.fasterxml.jackson.core.base.ParserMinimalBase._throwInvalidSpace(ParserMinimalBase.java:713) at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._skipWSOrEnd(ReaderBasedJsonParser.java:2462) at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextToken(ReaderBasedJsonParser.java:698) at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:4762) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4668) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3630) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3598) at org.example.GreetClientHandler.channelRead0(GreetClient.java:73) at org.example.GreetClientHandler.channelRead0(GreetClient.java:54) at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:840)
最新发布
08-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值