温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

java中netty怎么用

发布时间:2021-07-23 10:12:23 来源:亿速云 阅读:204 作者:小新 栏目:编程语言

这篇文章将为大家详细讲解有关java中netty怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

正文

代码部分

新建一个maven项目

首先在pom.xml中导入:

 <!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
    <dependency>
      <groupId>io.netty</groupId>
      <artifactId>netty-all</artifactId>
      <version>5.0.0.Alpha1</version>
    </dependency>

服务端
1. DiscardServer类,netty的服务端

public class DiscardServer {
  public void run(int port) throws Exception {
    EventLoopGroup bossGroup = new NioEventLoopGroup();
    EventLoopGroup workerGroup = new NioEventLoopGroup();
    System.out.println("准备运行端口:" + port);
    try {
      ServerBootstrap b = new ServerBootstrap();
      b = b.group(bossGroup, workerGroup)
          .channel(NioServerSocketChannel.class)
          .option(ChannelOption.SO_BACKLOG, 128)
          .childHandler(new ChildChannelHandler());
      //绑定端口,同步等待成功
      ChannelFuture f = b.bind(port).sync();
      //等待服务监听端口关闭
      f.channel().closeFuture().sync();
    } finally {
      //退出,释放线程资源
      workerGroup.shutdownGracefully();
      bossGroup.shutdownGracefully();
    }
  }
  public static void main(String[] args) throws Exception {
    new DiscardServer().run(8080);
  }
}

2. ChildChannelHandler类:

public class ChildChannelHandler extends ChannelInitializer<SocketChannel> {

  protected void initChannel(SocketChannel socketChannel) throws Exception {
    socketChannel.pipeline().addLast(new DiscardServerHandler());
  }
}

3. DiscardServerHandler类

在这里是继承的ChannelHandlerAdapter类,当然还可以继承其他的类,例如SimpleChannelInboundHandler,ChannelInboundHandlerAdapter都可以

public class DiscardServerHandler extends ChannelHandlerAdapter {
  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) {

    try {
      ByteBuf in = (ByteBuf) msg;
      System.out.println("传输内容是");
      System.out.println(in.toString(CharsetUtil.UTF_8));
      ByteBuf resp= Unpooled.copiedBuffer("收到信息$".getBytes());
      ctx.writeAndFlush(resp);
    } finally {
      ReferenceCountUtil.release(msg);
    }
  }
  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    // 出现异常就关闭
    cause.printStackTrace();
    ctx.close();
  }
}

启动netty服务;

好了,到这里就能开始接收数据了;

客服端

1.TimeClient类

public class TimeClient {
  public void connect(int port,String host)throws Exception{
    //配置客户端
    System.out.println(port+"--"+host);
    EventLoopGroup eventLoopGroup=new NioEventLoopGroup();
    try {
      Bootstrap b=new Bootstrap();
      b.group(eventLoopGroup).channel(NioSocketChannel.class)
          .option(ChannelOption.TCP_NODELAY,true)
          .handler(new ChannelInitializer<SocketChannel>() {
            protected void initChannel(SocketChannel socketChannel) throws Exception {
              socketChannel.pipeline().addLast(new TimeClientHandler());
            }
          });
      //绑定端口,同步等待成功
      ChannelFuture f = b.connect(host,port).sync();
      //等待服务监听端口关闭
      f.channel().closeFuture().sync();
    }finally {
      //优雅退出,释放线程资源
      eventLoopGroup.shutdownGracefully();
    }
  }
  public static void main(String[] args) throws Exception {
    new TimeClient().connect(8090,"localhost");
  }
}

2.TimeClientHandler 类

public class TimeClientHandler extends ChannelHandlerAdapter {
  private byte[] req;
  public TimeClientHandler(){
    req="$tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00$".getBytes();
  }
  @Override
  public void channelActive(ChannelHandlerContext ctx) throws Exception {
    ByteBuf message=null;
    for(int i=0;i<100;i++){
      message=Unpooled.buffer(req.length);
      message.writeBytes(req);
      ctx.writeAndFlush(message);
    }
  }
  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) {
    try {
      ByteBuf in = (ByteBuf) msg;
      System.out.println(in.toString(CharsetUtil.UTF_8));
    } finally {
      ReferenceCountUtil.release(msg);
    }
  }
  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    // 出现异常就关闭
    cause.printStackTrace();
    ctx.close();
  }
}

在channelActive类中向服务端发送100次消息

先启动服务端,再启动客户端;

测试结果一:

服务端:

传输内容是
$tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00$$tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00$$tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00$$tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00$$tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00$$tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00$$tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00$$tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00$$tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00$$tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00$$tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00$$tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00$$tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00$$tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00$$tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00$$tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00$$tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00$$tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00$$tmb00035ET3318/08/22 11:5704026.7
传输内容是
5,027.31,20.00,20.00$$tmb00035ET3318/08/22

客户端:

8080--localhost
收到信息收到信息收到信息收到信息收到信息收到信息收到信息收到信息收到信息收到信息收到信息收到信息收到信息收到信息收到信息收到信息收到信息收到信息收到信息收到信息收到信息收到信息收到信息收到信息收到信息收到信息收到信息收到信息

由于内容太多,就不都贴出来了j,直接写结果吧:

客户端发送100次数据,但是服务端只收到了28次,然后服务端向客户端返回28次数据,客户端却只收到一次;

可以发现服务端接收的数据不是完整接收的,这里出现了拆包,粘包的问题

这里就不讨论拆包,粘包了,百度一大堆,相信你也能看明白;

解决粘包,拆包的问题

解决拆包粘包的方法有很多:

  • 消息定长,固定每个消息的固定长度

  • 在消息末尾使用换行符对消息进行分割,或者使用其他特殊字符来对消息进行分割;

  • 将消息分为消息头和消息体,消息头中包含标识消息总长度;

  • 更复杂的,或者其他的协议。

由于我负责的这个项目户端发送是由$开始和结束的数据,返回的数据我也设置的$结束,所以我选择了第二种方法;

只需要在服务端的DiscardServerHandler中和客户端的ChannelInitializer中添加几行相同的代码就行了;

服务端:

public class ChildChannelHandler extends ChannelInitializer<SocketChannel> {

  protected void initChannel(SocketChannel socketChannel) throws Exception {
    ByteBuf byteBuf= Unpooled.copiedBuffer("$".getBytes());
    socketChannel.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,byteBuf));
    socketChannel.pipeline().addLast(new DiscardServerHandler());
  }
}

客户端:

在如下的位置添加如下的代码:

 .handler(new ChannelInitializer<SocketChannel>() {
            protected void initChannel(SocketChannel socketChannel) throws Exception {
              ByteBuf byteBuf= Unpooled.copiedBuffer("$".getBytes());
              socketChannel.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,byteBuf));
              socketChannel.pipeline().addLast(new TimeClientHandler());
            }
          });

测试结果

这里我就不发送100次数据了,值发送10次:

服务端:

传输内容是
tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00
传输内容是
tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00
传输内容是
tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00
传输内容是
tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00
传输内容是
tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00
传输内容是
tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00
传输内容是
tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00
传输内容是
tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00
传输内容是
tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00
传输内容是
tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00

客户端:

收到信息
收到信息
收到信息
收到信息
收到信息
收到信息
收到信息
收到信息
收到信息
收到信息

解决我所遇到的问题了;

关于“java中netty怎么用”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI