二、Netty实现服务器与客户端完整交互连接实战

版权声明:如需转载,请标明转载出处! https://blog.csdn.net/Z0157/article/details/82825790

        本节内容是代码实现服务器与客户端完整连接过程。整体把控netty的工作流程。我们先不要被某个类,某个api的封装深入挖掘,这样你会踩很多坑,陷入进去而拔不出来,后面我会一一讲解,源码剖析工作原理。这就是我个人学习技术的一种方法,深入浅出,慢慢彻底熟悉netty。我们先学会用,然后把它切分若干块,慢慢吞噬。

代码实现:

详细:

package com.zhurong.netty.test2;

import com.zhurong.netty.test1.TestServerInitializer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * Description:
 * User: zhurong
 * Date: 2018-09-19  23:17
 */
public class NettyServer {

    public static void main(String[] args) {
        //接收连接
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        //连接发送给work
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            System.out.println("服务器启动成功!");
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).
                    childHandler(new NettyInitializer());
            ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();
            channelFuture.channel().closeFuture().sync();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }

    }

}

  

package com.zhurong.netty.test2;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

/**
 * 此处定义客户端和服务器端传递的是字符串所以用了String
 * Description:
 * User: zhurong
 * Date: 2018-09-19  23:30
 */
public class NettyServerHandler extends SimpleChannelInboundHandler<String> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        System.out.println(ctx.channel().remoteAddress()+"------>"+msg);
          //返回数据给客户端,是一个异步的操作
        ctx.channel().writeAndFlush("server tell you hello");
    }

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

import com.zhurong.netty.test1.TestHttpServerHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;

/**
 * Description: 客户端与服务器端连接一旦创建,这个类中方法就会被回调
 * User: zhurong
 * Date: 2018-09-19  21:29
 */
public class NettyInitializer 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 StringEncoder(CharsetUtil.UTF_8));
        pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
        pipeline.addLast(new NettyServerHandler());
    }
}
package com.zhurong.netty.test2;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

/**
 * Description:
 * User: zhurong
 * Date: 2018-09-19  23:37
 */
public class NettyClient {

    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup eventExecutors = new NioEventLoopGroup();
        try {
            System.out.println("客户端启动成功");
            Bootstrap bootstrap =  new Bootstrap();
            bootstrap.group(eventExecutors).channel(NioSocketChannel.class).handler(new NettyClientInitializer());
            ChannelFuture channelFuture = bootstrap.connect("localhost",8899).sync();
            channelFuture.channel().closeFuture().sync();

        }finally {
            eventExecutors.shutdownGracefully();
        }

    }
}
package com.zhurong.netty.test2;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

/**
 * Description:
 * User: zhurong
 * Date: 2018-09-23  22:01
 */
public class NettyClientHandler extends SimpleChannelInboundHandler<String> {


    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        System.out.println("收到服务器的消息:"+ctx.channel().remoteAddress());
        System.out.println("msg:"+ msg);
//        ctx.writeAndFlush("from client "+ System.currentTimeMillis());
    }

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

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ctx.writeAndFlush("客户端第一条信息");
    }
}
package com.zhurong.netty.test2;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;

/**
 * Description: 客户端与服务器端连接一旦创建,这个类中方法就会被回调
 * User: zhurong
 * Date: 2018-09-19  21:29
 */
public class NettyClientInitializer 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 StringEncoder(CharsetUtil.UTF_8));
        pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
        pipeline.addLast(new NettyClientHandler());
    }
}

猜你喜欢

转载自blog.csdn.net/Z0157/article/details/82825790