Netty入門之用戶端與服務端通訊(二)

來源:互聯網
上載者:User

標籤:loop   worker   ble   tin   oev   active   extends   str   inbound   

Netty入門之用戶端與服務端通訊(二)

一.簡介

  在上一篇博文中筆者寫了關於Netty入門級的Hello World程式。書接上回,本博文是關於用戶端與服務端的通訊,感覺也沒什麼好說的了,直接上代碼吧。

二.用戶端與服務端的通訊

2.1 服務端啟動程式

public class MyServer {    public static void main(String[] args) throws InterruptedException {        EventLoopGroup bossGroup = new NioEventLoopGroup();        EventLoopGroup workerGroup = new NioEventLoopGroup();                try{            ServerBootstrap serverBootstrap = new ServerBootstrap();                        serverBootstrap.group(bossGroup, workerGroup)                           .channel(NioServerSocketChannel.class)                           .childHandler(new MyInitializer());                        ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();            channelFuture.channel().closeFuture().sync();        }finally{            bossGroup.shutdownGracefully();            workerGroup.shutdownGracefully();        }    }}

2.2 服務端通道初始化程式

public class MyInitializer extends ChannelInitializer<SocketChannel>{    @Override    protected void initChannel(SocketChannel ch) throws Exception {        ChannelPipeline pipeline =  ch.pipeline();        /**         * LengthFieldBasedFrameDecoder: 基於長度屬性的幀解碼器。         * 用戶端傳遞過來的資料格式為:         *  BEFORE DECODE (14 bytes)         AFTER DECODE (14 bytes)           *    +--------+----------------+      +--------+----------------+           *    | Length | Actual Content |----->| Length | Actual Content |           *    | 0x000C | "HELLO, WORLD" |      | 0x000C | "HELLO, WORLD" |           *    +--------+----------------+      +--------+----------------+           * 5個參數依次為:1.(maxFrameLength)每幀資料的最大長度.         *              2.(lengthFieldOffset)length屬性在幀中的位移量。         *           3.(lengthFieldLength)length屬性的長度,需要與用戶端 LengthFieldPrepender設定的長度一致,         *               值的取值只能為1, 2, 3, 4, 8         *           4.(lengthAdjustment)長度調節值, 當資訊長度包含長度時候,用於修正資訊的長度。         *           5.(initialBytesToStrip)在擷取真實的內容的時候,需要忽略的長度(通常就是length的長度)。         *                    * 參考: http://blog.csdn.net/educast/article/details/47706599         */        pipeline.addLast("lengthFieldBasedFrameDecoder",                             new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 2, 0, 2));        /**         * LengthFieldPrepender: length屬性在幀中的長度。只能為1,2,3,4,8。         * 該值與對應的用戶端(或者服務端)在解碼時候使用LengthFieldBasedFrameDecoder中所指定的lengthFieldLength         * 的值要保持一致。         */        pipeline.addLast("lengthFieldPrepender", new LengthFieldPrepender(3));        //StringDecoder字串的解碼器, 主要用於處理編碼格式        pipeline.addLast("stringDecoder", new StringDecoder(CharsetUtil.UTF_8));        //StringDecoder字串的編碼器,主要用於指定字串的編碼格式        pipeline.addLast("stringEncoder", new StringEncoder(CharsetUtil.UTF_8));                pipeline.addLast(new MyHandler()); //自訂的Handler    }}

2.3 自訂Handler

public class MyHandler extends SimpleChannelInboundHandler<String>{    @Override    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {        System.out.println(ctx.channel().remoteAddress() + ":" + msg);        ctx.channel().writeAndFlush("from server: 草泥馬");    }        @Override    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {        System.out.println(System.currentTimeMillis() + "********");        System.out.println("server handler added**********");    }        @Override    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {        System.out.println(System.currentTimeMillis() + "********");        System.out.println("server channel register****");    }        @Override    public void channelActive(ChannelHandlerContext ctx) throws Exception {        System.out.println(System.currentTimeMillis() + "********");        System.out.println("server channel actieve****");    }        @Override    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {        cause.printStackTrace();        ctx.close();    }}

2.4用戶端啟動程式

public class MyClient {    public static void main(String[] args) throws InterruptedException {        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();                try{            Bootstrap bootstrap = new Bootstrap();            bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class).handler(new ClientInitializer());                        ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 8899).sync();            channelFuture.channel().closeFuture().sync();        }finally{            eventLoopGroup.shutdownGracefully();        }    }}

2.5用戶端通道初始化

public class ClientInitializer extends ChannelInitializer<SocketChannel>{    @Override    protected void initChannel(SocketChannel ch) throws Exception {        ChannelPipeline pipeline =  ch.pipeline();        pipeline.addLast("lengthFieldBasedFrameDecoder",                             new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 2, 0, 2));        pipeline.addLast("lengthFieldPrepender", new LengthFieldPrepender(3));        pipeline.addLast("stringDecoder", new StringDecoder(CharsetUtil.UTF_8));        pipeline.addLast("stringEncoder", new StringEncoder(CharsetUtil.UTF_8));                pipeline.addLast(new MyClientHandler());    }}

2.5用戶端自訂Handler

public class MyClientHandler extends SimpleChannelInboundHandler<String>{    @Override    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {        System.out.println(ctx.channel().remoteAddress());        System.out.println(msg);        ctx.channel().writeAndFlush("to Server: 草泥馬");    }        @Override    public void channelActive(ChannelHandlerContext ctx) throws Exception {        System.out.println(System.currentTimeMillis() + "...........");        ctx.channel().writeAndFlush("來自於用戶端的問候!");        System.out.println("client channel Active...");    }        @Override    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {        System.out.println(System.currentTimeMillis() + "...........");        System.out.println("client hanlder added...");    }        @Override    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {        System.out.println(System.currentTimeMillis() + "...........");        System.out.println("client channel register...");    }        @Override    public void channelInactive(ChannelHandlerContext ctx) throws Exception {        System.out.println("client channel inactive...");    }        @Override    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {        System.out.println("client channel unregister...");    }        @Override    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {        cause.printStackTrace();        ctx.close();    }}

三. 運行測試

運行服務端啟動代碼,然後在運行用戶端啟動代碼,就可以看見千萬隻"草泥馬"在崩騰。

 

Netty入門之用戶端與服務端通訊(二)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.