Java服务器端编程Java学习笔记

netty基本使用- socket通信

2017-07-24  本文已影响2994人  持续进步者

netty 支持socket通信

系列文章

[netty 基本使用- 作为http服务器][gcssloop]
[gcssloop]: http://www.jianshu.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 常用的处理大数据分包传输问题的解决类。

LengthFieldPrepender 编码类

编码类,自动将

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

| "HELLO, WORLD" |

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

格式的数据转换成

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

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

格式的数据

参考文章

[netty 数据分包、组包、粘包处理机制][123]
[123]: http://blog.163.com/linfenliang@126/blog/static/127857195201210821145721/

上一篇下一篇

猜你喜欢

热点阅读