Netty簡單demo

Netty簡單demo

​ 上篇博客簡單介紹了Netty的一些基礎概念和組件,這次就來寫一個簡單的demo,因爲公司需要的是TCP服務端,所以這次的demo就寫一個TCP服務端。下面就直接上代碼。

​ 首先是主類,裏面也放着Netty的啓動方法和執行流程。代碼如下:

package nettytrain;


import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
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.NioServerSocketChannel;

/**
 * TCPServerTrain.java
 * Description:  netty服務端的練習
 *
 * @author Peng Shiquan
 * @date 2020/6/18
 */
public class TCPServerTrain {
    //默認端口
    private Integer port = 10000;

    public TCPServerTrain(Integer port) {
        this.port = port;
    }

    public void run() throws Exception {
        // 接收傳入的連接
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        //處理傳入的連接,一般是bossGroup的二倍
        EventLoopGroup workGroup = new NioEventLoopGroup();
        try {
            //服務端應用開發的入口
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            //設置主從線程池
            serverBootstrap.group(bossGroup, workGroup)
                    //指定通道channel的類型,因爲是服務端,所以是NioServerSocketChannel
                    .channel(NioServerSocketChannel.class)
                    //設置子通道也就是SocketChannel的處理器
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast(new TCPServerHandler());
                        }
                    })
                    //配置ServerSocketChannel的選項
                    .option(ChannelOption.SO_BACKLOG, 128)
                    //配置子通道也就是SocketChannel的選項
                    .childOption(ChannelOption.SO_KEEPALIVE, true);
            //綁定並偵聽某個端口
            ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
            //如何沒有客戶端連接就會關閉Channel和兩個線程池
            channelFuture.channel().closeFuture().sync();
        } finally {
            /**
             * 關閉線程池
             */
            workGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }

    }

    public static void main(String[] args) throws Exception {
        int port = 10000;
        if (args.length > 0) {
            port = Integer.parseInt(args[0]);
        }
        new TCPServerTrain(port).run();

    }

}

​ 代碼裏面的註釋已經很清楚了,沒有什麼可以細講的地方。下面的就是業務處理類,自己的業務處理主要放在這裏。代碼:

package nettytrain;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
import io.netty.util.ReferenceCountUtil;
import network_train.ARPojo;
import network_train.ARSwitch;

/**
 * TCPServerHandler.java
 * Description: 主要的業務處理類
 *
 * @author Peng Shiquan
 * @date 2020/6/18
 */
public class TCPServerHandler extends ChannelInboundHandlerAdapter {

    /**
     * Description: 通道的讀取操作方法
     *
     * @param ctx
     * @param msg
     * @return void
     * @Author: Peng Shiquan
     * @Date: 2020/6/19
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        try {
            ByteBuf recvmg = (ByteBuf) msg;
            String line = recvmg.toString(CharsetUtil.UTF_8);
            System.err.println("接收到消息" + line);
            if (line.contains("BG") && line.contains("ED")) {
                ARPojo arPojo = ARSwitch.LineSwitch(line);
                System.err.println("轉換爲pojo對象" + arPojo.toString());
            }
        } finally {
            // 釋放msg
            ReferenceCountUtil.release(msg);
        }
    }


    /**
     * Description:  異常捕獲
     *
     * @param ctx
     * @param cause
     * @return void
     * @Author: Peng Shiquan
     * @Date: 2020/6/19
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}

​ 也是沒有什麼可以講的地方,這裏的業務處理我放在其他的地方了,所以這裏的代碼很少,每個人的業務不同,所以業務處理也不同。

​ 下面就說說遇到的問題。就是通道讀取的方法,剛開始不知道怎麼處理msg,後來轉換成ByteBuf,再轉換的String,這個地方不知道處理的對不對。其他的問題就是這個代碼沒有考慮到粘包的現象,現在還沒有涉及到,所以沒有寫,後面慢慢補上。

​ 就這樣吧,結束。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章