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,这个地方不知道处理的对不对。其他的问题就是这个代码没有考虑到粘包的现象,现在还没有涉及到,所以没有写,后面慢慢补上。

​ 就这样吧,结束。

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