溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java中netty怎么用

發(fā)布時間:2021-07-23 10:12:23 來源:億速云 閱讀:214 作者:小新 欄目:編程語言

這篇文章將為大家詳細講解有關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();
      //等待服務監(jiān)聽端口關閉
      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 {
    // 出現(xiàn)異常就關閉
    cause.printStackTrace();
    ctx.close();
  }
}

啟動netty服務;

好了,到這里就能開始接收數(shù)據(jù)了;

客服端

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();
      //等待服務監(jiān)聽端口關閉
      f.channel().closeFuture().sync();
    }finally {
      //優(yōu)雅退出,釋放線程資源
      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 {
    // 出現(xiàn)異常就關閉
    cause.printStackTrace();
    ctx.close();
  }
}

在channelActive類中向服務端發(fā)送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,直接寫結果吧:

客戶端發(fā)送100次數(shù)據(jù),但是服務端只收到了28次,然后服務端向客戶端返回28次數(shù)據(jù),客戶端卻只收到一次;

可以發(fā)現(xiàn)服務端接收的數(shù)據(jù)不是完整接收的,這里出現(xiàn)了拆包,粘包的問題

這里就不討論拆包,粘包了,百度一大堆,相信你也能看明白;

解決粘包,拆包的問題

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

  • 消息定長,固定每個消息的固定長度

  • 在消息末尾使用換行符對消息進行分割,或者使用其他特殊字符來對消息進行分割;

  • 將消息分為消息頭和消息體,消息頭中包含標識消息總長度;

  • 更復雜的,或者其他的協(xié)議。

由于我負責的這個項目戶端發(fā)送是由$開始和結束的數(shù)據(jù),返回的數(shù)據(jù)我也設置的$結束,所以我選擇了第二種方法;

只需要在服務端的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());
            }
          });

測試結果

這里我就不發(fā)送100次數(shù)據(jù)了,值發(fā)送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問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI