netty基本使用- socket通信

netty 支持socket通信

  • 1,netty 大大簡化了socket開發,提高了socket的性能。
  • 2,Netty提供異步的、事件驅動的網絡應用程序框架和工具,
    用以快速開發高性能、高可靠性的網絡服務器和客戶端程序。

系列文章

[netty 基本使用- 作為http服務器][gcssloop]
[gcssloop]: http://www.lxweimin.com/p/cd88723c96dc

服務器端代碼

ServerSocket.java

    public class ServerSocket {
    public static void main(String ...arg) throws Exception {

        //負責接收客戶端連接
        NioEventLoopGroup bossGroup = new NioEventLoopGroup();

        //負責處理連接
        NioEventLoopGroup wokerGroup = new NioEventLoopGroup();

        try{

            ServerBootstrap bootstrap = new ServerBootstrap();

            bootstrap.group(bossGroup,wokerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ServerInitializer());

            //綁定端口號
            ChannelFuture channelFuture = bootstrap.bind(9999).sync();
            channelFuture.channel().closeFuture().sync();

        } finally {
            bossGroup.shutdownGracefully();
            wokerGroup.shutdownGracefully();
        }

    }
}

** ServerInitializer.java **

public class ServerInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
      ChannelPipeline pipeline = ch.pipeline();

      //數據分包,組包,粘包
      pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,4,0,4));
      pipeline.addLast(new LengthFieldPrepender(4));

      pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
      pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));

      pipeline.addLast(new ServerHandler());


    }
}

** ServerHandler.java 處理業務 **

    public class ServerHandler extends SimpleChannelInboundHandler<String> {

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, String msg) throws   Exception {
            //接收到的數據
            System.out.println(ctx.channel().remoteAddress()+" , "+msg);
    
            //返回給客戶端的數據
            ctx.channel().writeAndFlush("server: "+ UUID.randomUUID());
        }
    
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws  Exception {
            cause.printStackTrace();
            ctx.close();
        }
    }

客戶端端代碼

** ClientSocket.java **

    public class ClientSocket {
    public static void main(String[] arg) throws Exception {
        NioEventLoopGroup eventLoopGroup = new NioEventLoopGroup();

        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class)
                    .handler(new Clientinitializer());

            ChannelFuture channelFuture = bootstrap.connect("localhost", 9999).sync();
            channelFuture.channel().closeFuture().sync();

        } finally {
            eventLoopGroup.shutdownGracefully();
        }
    }
}

** Clientinitializer.java **

    public class Clientinitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();

        //數據分包,組包,粘包
        pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,4,0,4));
        pipeline.addLast(new LengthFieldPrepender(4));

        pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
        pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));

        pipeline.addLast(new ClientHandler());

    }
}

**ClientHandler.java 處理業務 **

public class ClientHandler extends SimpleChannelInboundHandler<String> {

    //接收服務端數據&發送數據
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {

        System.out.println("客戶端接收到的消息: "+msg);

        ctx.writeAndFlush(LocalDateTime.now());

        //完成通信后關閉連接
        //ctx.close();
    }

    //和服務器建立連接
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
      ctx.writeAndFlush("在嗎?。。?!");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}

** 可以多次和服務器端通信的寫法 **

    public class ClientSocket2 {
    public static void main(String[] arg) throws Exception {
        NioEventLoopGroup eventLoopGroup = new NioEventLoopGroup();

        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class)
                    .handler(new Clientinitializer());

            ChannelFuture channelFuture = bootstrap.connect("localhost", 9999).sync();
            Channel channel = channelFuture.channel();

            //接收輸入的數據
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in, CharsetUtil.UTF_8));
            while (true) {
                String sendMsg = bufferedReader.readLine() ;
                if ("esc".equals(sendMsg)) {
                    channel.close();
                    break;
                }

                sendMsg += "\r\n";
                channel.writeAndFlush(sendMsg);
            }


        } finally {
            eventLoopGroup.shutdownGracefully();
        }
    }
}


LengthFieldBasedFrameDecoder

netty 常用的處理大數據分包傳輸問題的解決類。

  • maxFrameLength:解碼的幀的最大長度。
  • lengthFieldOffset: 長度屬性的起始位(偏移位),包中存放有整個大數據包長度的字節,這段字節的其實位置。
  • lengthFieldLength:長度屬性的長度,即存放整個大數據包長度的字節所占的長度。
  • lengthAdjustmen:長度調節值,在總長被定義為包含包頭長度時,修正信息長度。
  • initialBytesToStrip:跳過的字節數,根據需要我們跳過lengthFieldLength個字節,以便接收端直接接受到不含“長度屬性”的內容。

LengthFieldPrepender 編碼類

編碼類,自動將

+----------------+

| "HELLO, WORLD" |

+----------------+

格式的數據轉換成

+--------+----------------+

  • 0x000C | "HELLO, WORLD" |

+--------+----------------+

格式的數據

參考文章

[netty 數據分包、組包、粘包處理機制][123]
[123]: http://blog.163.com/linfenliang@126/blog/static/127857195201210821145721/

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 前奏 https://tech.meituan.com/2016/11/04/nio.html 綜述 netty通...
    jiangmo閱讀 5,918評論 0 13
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,991評論 19 139
  • 從三月份找實習到現在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發崗...
    時芥藍閱讀 42,373評論 11 349
  • 我和阿呆是同性戀人,昨晚我們一同在校道散步。 夏伏桑,夜歸涼,晚風習習。我們走著,一前一后,腳下生風,更像是在追逐...
    著邊閱讀 775評論 0 0
  • 我覺得姐姐的的內心可以用豇豆來形容,她是那種有不爽就隨時隨地發泄出來就好了;二姥的內心應該是一汪清泉,純白無暇;大...
    Amilyren閱讀 865評論 0 1