站長資訊網(wǎng)
        最全最豐富的資訊網(wǎng)站

        Netty搭建TCP服務(wù)器實踐

        在netty基本組件介紹中,我們大致了解了netty的一些基本組件,今天我們來搭建一個基于netty的Tcp服務(wù)端程序,通過代碼來了解和熟悉這些組件的功能和使用方法。

        首先我們自己創(chuàng)建一個Server類,命名為TCPServer

        第一步初始化ServerBootstrap,ServerBootstrap是netty中的一個服務(wù)器引導(dǎo)類,對ServerBootstrap的實例化就是創(chuàng)建netty服務(wù)器的入口

        public class TCPServer {
            private Logger log = LoggerFactory.getLogger(getClass());
            //端口號
            private int port=5080;
            //服務(wù)器運行狀態(tài)
            private volatile boolean isRunning = false;
            //處理Accept連接事件的線程,這里線程數(shù)設(shè)置為1即可,netty處理鏈接事件默認為單線程,過度設(shè)置反而浪費cpu資源
            private final EventLoopGroup bossGroup = new NioEventLoopGroup(1);
            //處理hadnler的工作線程,其實也就是處理IO讀寫 。線程數(shù)據(jù)默認為 CPU 核心數(shù)乘以2
            private final EventLoopGroup workerGroup = new NioEventLoopGroup();
           
            public void init() throws Exception{
                //創(chuàng)建ServerBootstrap實例
                ServerBootstrap serverBootstrap=new ServerBootstrap();
                //初始化ServerBootstrap的線程模型
                serverBootstrap.group(workerGroup,workerGroup);//
                //設(shè)置將要被實例化的ServerChannel類
                serverBootstrap.channel(NioServerSocketChannel.class);//
                //在ServerChannelInitializer中初始化ChannelPipeline責任鏈,并添加到serverBootstrap中
                serverBootstrap.childHandler(new ServerChannelInitializer());
                //標識當服務(wù)器請求處理線程全滿時,用于臨時存放已完成三次握手的請求的隊列的最大長度
                serverBootstrap.option(ChannelOption.SO_BACKLOG, 1024);
                // 是否啟用心跳?;顧C機制
                serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);   
                //綁定端口后,開啟監(jiān)聽
                ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
                if(channelFuture.isSuccess()){
                    System.out.println(“TCP服務(wù)啟動 成功—————“);
                }
            }
           
            /**
            * 服務(wù)啟動
            */
            public synchronized void startServer() {
                try {
                      this.init();
                }catch(Exception ex) {
                   
                }
            }
           
            /**
            * 服務(wù)關(guān)閉
            */
            public synchronized void stopServer() {
                if (!this.isRunning) {
                    throw new IllegalStateException(this.getName() + ” 未啟動 .”);
                }
                this.isRunning = false;
                try {
                    Future<?> future = this.workerGroup.shutdownGracefully().await();
                    if (!future.isSuccess()) {
                        log.error(“workerGroup 無法正常停止:{}”, future.cause());
                    }

                    future = this.bossGroup.shutdownGracefully().await();
                    if (!future.isSuccess()) {
                        log.error(“bossGroup 無法正常停止:{}”, future.cause());
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                this.log.info(“TCP服務(wù)已經(jīng)停止…”);
            }
           
            private String getName() {
                return “TCP-Server”;
            }
        }

         

        上面的代碼中主要使用到的ServerBootstrap類的方法有以下這些:

        group  :設(shè)置SeverBootstrap要用到的EventLoopGroup,也就是定義netty服務(wù)的線程模型,處理Acceptor鏈接的主”線程池”以及用于I/O工作的從”線程池”;

        channel:設(shè)置將要被實例化的SeverChannel類;

        option :指定要應(yīng)用到新創(chuàng)建SeverChannel的ChannelConfig的ChannelOption.其實也就是服務(wù)本身的一些配置;

        chidOption:子channel的ChannelConfig的ChannelOption。也就是與客戶端建立的連接的一些配置;

        childHandler:設(shè)置將被添加到已被接收的子Channel的ChannelPipeline中的ChannelHandler,其實就是讓你在里面定義處理連接收發(fā)數(shù)據(jù),需要哪些ChannelHandler按什么順序去處理;

        第二步接下來我們實現(xiàn)ServerChannelInitializer類,這個類繼承實現(xiàn)自netty的ChannelInitializer抽象類,這個類的作用就是對channel(連接)的ChannelPipeline進行初始化工作,說白了就是你要把處理數(shù)據(jù)的方法添加到這個任務(wù)鏈中去,netty才知道每一步拿著socket連接和數(shù)據(jù)去做什么。

         

        @ChannelHandler.Sharable
        public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {
            static final EventExecutorGroup group = new DefaultEventExecutorGroup(2);
           
            public ServerChannelInitializer() throws InterruptedException {
            }
           
            @Override
            protected void initChannel(SocketChannel socketChannel) throws Exception {   
                ChannelPipeline pipeline = socketChannel.pipeline();
                //IdleStateHandler心跳機制,如果超時觸發(fā)Handle中userEventTrigger()方法
                pipeline.addLast(“idleStateHandler”,
                        new IdleStateHandler(15, 0, 0, TimeUnit.MINUTES));
                // netty基于分割符的自帶解碼器,根據(jù)提供的分隔符解析報文,這里是0x7e;1024表示單條消息的最大長度,解碼器在查找分隔符的時候,達到該長度還沒找到的話會拋異常
        //        pipeline.addLast(
        //                new DelimiterBasedFrameDecoder(1024, Unpooled.copiedBuffer(new byte[] { 0x7e }),
        //                        Unpooled.copiedBuffer(new byte[] { 0x7e })));
                //自定義編解碼器
                pipeline.addLast(
                        new MessagePacketDecoder(),
                        new MessagePacketEncoder()
                        );
                //自定義Hadler
                pipeline.addLast(“handler”,new TCPServerHandler());
                //自定義Hander,可用于處理耗時操作,不阻塞IO處理線程
                pipeline.addLast(group,”BussinessHandler”,new BussinessHandler());
            }
        }

         

        這里我們注意下

        pipeline.addLast(group,”BussinessHandler”,new BussinessHandler());

        在這里我們可以把一些比較耗時的操作(如存儲、入庫)等操作放在BussinessHandler中進行,因為我們?yōu)樗鼏为毞峙淞薊ventExecutorGroup 線程池執(zhí)行,所以說即使這里發(fā)生阻塞,也不會影響TCPServerHandler中數(shù)據(jù)的接收。

        最后就是各個部分的具體實現(xiàn)

        解碼器的實現(xiàn):

         

        public class MessagePacketDecoder extends ByteToMessageDecoder
        {

            public MessagePacketDecoder() throws Exception
            {
            }

            @Override
            protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws Exception
            {
                try {
                    if (buffer.readableBytes() > 0) {
                        // 待處理的消息包
                        byte[] bytesReady = new byte[buffer.readableBytes()];
                        buffer.readBytes(bytesReady);
                        //這之間可以進行報文的解析處理
                        out.add(bytesReady );
                    }
                }finally {
                   
                }
            }

        }

         

        編碼器的實現(xiàn)

         

        public class MessagePacketEncoder extends MessageToByteEncoder<Object>
        {
            public MessagePacketEncoder()
            {
            }

            @Override
            protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception
            {
                try {
                    //在這之前可以實現(xiàn)編碼工作。
                    out.writeBytes((byte[])msg);
                }finally {
                   
                } 
            }
        }

         

        TCPServerHandler的實現(xiàn)

         

        public class TCPServerHandler extends ChannelInboundHandlerAdapter {   
            public TCPServerHandler() {
            }
           
            @Override 
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 
              //拿到傳過來的msg數(shù)據(jù),開始處理
            }
           
            //檢測到空閑連接,觸發(fā)
            @Override
            public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
              //這里可做一些斷開連接的處理 
            }
        }

         

        BussinessHandler的實???與TCPServerHandler基本類似,它可以處理一些相對比較耗時的操作,我們這里就不實現(xiàn)了。

        通過以上的代碼我們可以看到,一個基于netty的TCP服務(wù)的搭建基本就是三大塊:

        1、對引導(dǎo)服務(wù)器類ServerBootstrap的初始化;

        2、對ChannelPipeline的定義,也就是把多個ChannelHandler組成一條任務(wù)鏈;

        3、對 ChannelHandler的具體實現(xiàn),其中可以有編解碼器,可以有對收發(fā)數(shù)據(jù)的業(yè)務(wù)處理邏輯;

        以上代碼只是在基于netty框架搭建一個最基本的TCP服務(wù),其中包含了一些netty基本的特性和功能,當然這只是netty運用的一個簡單的介紹,如有不正確的地方還望指出與海涵。

        贊(0)
        分享到: 更多 (0)
        網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
        主站蜘蛛池模板: 久久久久久九九99精品 | 国产午夜福利精品一区二区三区| 中文字幕亚洲综合精品一区| 日韩精品中文字幕第2页| 四虎成人www国产精品| 国产在线精品免费aaa片| 亚洲精品专区在线观看| 久久久国产精品| 91精品国产综合久久香蕉 | 51精品资源视频在线播放| 日韩精品国产另类专区| 四虎成人精品| 精品国产亚洲一区二区在线观看| 91久久精品电影| 99精品视频在线观看| 久久久久久九九99精品| 亚洲AV无码精品色午夜果冻不卡| 日韩专区亚洲精品欧美专区| 国产一区二区精品久久凹凸| 国产精品hd免费观看| 四虎国产精品永久一区| 精品免费tv久久久久久久| 99精品在线观看| 99精品无人区乱码在线观看| 国产一精品一AV一免费| 国产精品igao视频网| 国产乱子伦精品无码码专区| 色久综合网精品一区二区| 最新精品露脸国产在线| 办公室久久精品| 国产精品天干天干综合网| 精品国产91久久久久久久a| 国产人成精品午夜在线观看| 中文字幕精品无码一区二区| 国语自产精品视频| 国产精品成人观看视频| 99精品久久久久久久婷婷| 热久久国产精品| 97精品人妻一区二区三区香蕉| 91精品免费久久久久久久久| 91亚洲国产成人久久精品|