Java NIO的netty实现

服务端:

package netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * 时间服务器,当有客户端请求时,返回服务端当前时间
 */

public class TimeServer {

    public void bind(int port){

        //NioEventLoopGroup是一个线程组,它包含了一组NIO线程,
        // 这里的两个线程组一个是用于服务端接受客户端的连接,
        // 另一个用于SocketChannel的网络读写
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            //netty用于启动NIO服务端的辅助启动类
            ServerBootstrap b = new ServerBootstrap();

            //设置线程组
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)//设置channel
                    .option(ChannelOption.SO_BACKLOG, 1024)//设置channel的TCP参数
                    .childHandler(new ChildChannelHandler());//绑定IO事件处理类

            //绑定监听端口,调用同步阻塞方法等待绑定完成
            ChannelFuture f = b.bind(port).sync();
            //阻塞,等待服务端链路关闭后main函数才退出
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            //优雅退出,释放跟shutdownGracefully相关联的所有资源
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    private class ChildChannelHandler extends ChannelInitializer<SocketChannel>{

        @Override
        protected void initChannel(SocketChannel serverSocket) throws Exception {
            //增加时间处理类
        serverSocket.pipeline().addLast(new TimeServerHandler());
        }
    }

    public static void main(String[] args) {
        int port = 8080;
        new TimeServer().bind(port);
    }
}

服务端Handler:
package netty;


import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;

import java.util.Date;


/**
 * 对网络事件进行读写操作
 */
public class TimeServerHandler extends ChannelHandlerAdapter {

    /**
     * 当异常发生时
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //super.exceptionCaught(ctx, cause);
        ctx.close();
    }

    /**
     * 读取缓冲区里面的数据,处理并返回
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //super.channelRead(ctx, msg);
        ByteBuf buf = (ByteBuf) msg;
        //buf.readableBytes()返回缓冲区可读的字节数
        byte [] bytes = new byte[buf.readableBytes()];
        //读取缓冲区的数据至byte数组
        buf.readBytes(bytes);
        String data = new String(bytes,"UTF-8");
        String currentTime = "query time order".equals(data)? new Date(System.currentTimeMillis()).toString(): "bad order";
        //复制bytes数组的内容,构造一个缓冲区对象ByteBuf
        ByteBuf rsp = Unpooled.copiedBuffer(currentTime.getBytes());
        //异步发送消息给客户端
        ctx.write(rsp);
    }

    /**
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
       // super.channelReadComplete(ctx);
        //ctx.write(rsp)发送消息时不是马上发送,而是将消息发送到发送缓冲区,等到读完成后
        //再调用flush方法将发送缓冲区的消息全部写到SocketChannel中,发送给客户端
        ctx.flush();
    }
}

客户端:

package netty;

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

/**
 * netty的客户端
 */

public class TimeClient {

    public void connect(String host, int port){

        //NioEventLoopGroup是一个线程组,它包含了一组NIO线程
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            //客户端辅助启动类
            Bootstrap b = new Bootstrap();

            //设置线程组
            b.group(group)
                    .channel(NioSocketChannel.class)//设置Channel
                    .option(ChannelOption.TCP_NODELAY, true)//设置TCP的参数
                    .handler(new ChannelInitializer<SocketChannel>() {//匿名内部类设置handler
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast(new TimeClientHandler());
                        }
                    });
            //异步连接客户端,同步阻塞直到连接成功
        ChannelFuture f = b.connect(host, port).sync();
            //阻塞,等待客户端链路关闭后main函数才退出
        f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            group.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        String host = "127.0.0.1";
        int port = 8080;
        new TimeClient().connect(host, port);
    }
}

客户端的Handler:

package netty;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;

public class TimeClientHandler extends ChannelHandlerAdapter {

    private ByteBuf firstMessage;

    /**
     * 初始化ByteBuf,初始化发送给服务端的消息
     */
    public TimeClientHandler(){
        byte [] bytes = "query time order".getBytes();
        firstMessage = Unpooled.buffer(bytes.length);
        firstMessage.writeBytes(bytes);
    }

    /**
     * 连接服务端成功后开始发送消息
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //super.channelActive(ctx);
        ctx.writeAndFlush(firstMessage);
    }

    /**
     * 读取客户端的返回消息
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
       // super.channelRead(ctx, msg);
        ByteBuf  buf = (ByteBuf) msg;
        byte [] bytes = new byte[buf.readableBytes()];
        buf.readBytes(bytes);
        String time = new String(bytes, "UTF-8");
        System.out.println("receive time from server, time = " + time);
    }

    /**
     * 发生异常时关闭ctx
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //super.exceptionCaught(ctx, cause);
        ctx.close();
    }
}

解决半包读写问题:什么叫TCP的半包读写问题,就是TCP读取数据包时,不是一个报文一个报文的读取,有可能一次读取到2个或者以上的报文,这叫粘包,又或者将一个报文拆分成2部分读取,这叫拆包,以上这些都会导致半包读写问题;

服务端TimeServer的改造:

private class ChildChannelHandler extends ChannelInitializer<SocketChannel>{

    @Override
    protected void initChannel(SocketChannel serverSocket) throws Exception {
        //新增解码器
        serverSocket.pipeline().addLast(new LineBasedFrameDecoder(1024));
        serverSocket.pipeline().addLast(new StringDecoder());
    serverSocket.pipeline().addLast(new TimeServerHandler());
    }
}

服务端TimeServerHandler的改造:

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    //super.channelRead(ctx, msg);
    //直接返回解码后的body
    String body = (String) msg;
    System.out.println("the time server reveive order : " + body +"; the counter is :" + ++counter);
    String currentTime = "query time order".equals(body)? new Date(System.currentTimeMillis()).toString(): "bad order";
    currentTime = currentTime + System.getProperty("line.separator");
    //复制bytes数组的内容,构造一个缓冲区对象ByteBuf
    ByteBuf rsp = Unpooled.copiedBuffer(currentTime.getBytes());
    //异步发送消息给客户端
    ctx.write(rsp);
}

客户端TimeClient的改造:

b.group(group)
        .channel(NioSocketChannel.class)//设置Channel
        .option(ChannelOption.TCP_NODELAY, true)//设置TCP的参数
        .handler(new ChannelInitializer<SocketChannel>() {//匿名内部类设置handler
            @Override
            protected void initChannel(SocketChannel socketChannel) throws Exception {
                socketChannel.pipeline().addLast(new LineBasedFrameDecoder(1024));
                socketChannel.pipeline().addLast(new StringDecoder());
                socketChannel.pipeline().addLast(new TimeClientHandler());
            }
        });

客户端TimeClientHandler的改造:

/**
 * 初始化ByteBuf,初始化发送给服务端的消息
 */
public TimeClientHandler(){
    req = ("query time order" + System.getProperty("line.separator")).getBytes();
    System.out.println("line.separator = " +  System.getProperty("line.separator"));
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
    //super.channelActive(ctx);
    ByteBuf buf = null;
    for(int i=0; i< 100; i++){
        buf = Unpooled.buffer(req.length);
        buf.writeBytes(req);
        ctx.writeAndFlush(buf);
    }

}
/**
 * 读取客户端的返回消息
 * @param ctx
 * @param msg
 * @throws Exception
 */
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
   // super.channelRead(ctx, msg);
    String  body = (String) msg;
    System.out.println("Now is :" + body +"; the counter is :" + ++counter );
}

 以DelimiterBasedFrameDecoder特定分割符做结束标志的消息的解码:

EchoServer:
package delimiter;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import nettybanbao.TimeServerHandler;

/**
 * 时间服务器,当有客户端请求时,返回服务端当前时间
 */

public class EchoServer {

    public void bind(int port){

        //NioEventLoopGroup是一个线程组,它包含了一组NIO线程,
        // 这里的两个线程组一个是用于服务端接受客户端的连接,
        // 另一个用于SocketChannel的网络读写
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            //netty用于启动NIO服务端的辅助启动类
            ServerBootstrap b = new ServerBootstrap();

            //设置线程组
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)//设置channel
                    .option(ChannelOption.SO_BACKLOG, 100)//设置channel的TCP参数
                    .childHandler(new ChildChannelHandler());//绑定IO事件处理类

            //绑定监听端口,调用同步阻塞方法等待绑定完成
            ChannelFuture f = b.bind(port).sync();
            //阻塞,等待服务端链路关闭后main函数才退出
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            //优雅退出,释放跟shutdownGracefully相关联的所有资源
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    private class ChildChannelHandler extends ChannelInitializer<SocketChannel>{

        @Override
        protected void initChannel(SocketChannel serverSocket) throws Exception {

            //创建分隔符缓冲对象ByteBuf,以“$_”作为分隔符
            ByteBuf delimter = Unpooled.copiedBuffer("$_".getBytes());
            //DelimiterBasedFrameDecoder有2个参数,
            // 第一个参数是单条消息的最大长度,当达到该长度后还没有查找到分隔符,则抛出异常
            //第二个参数是分隔符缓冲对象
            serverSocket.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimter));
            serverSocket.pipeline().addLast(new StringDecoder());
        serverSocket.pipeline().addLast(new EchoServerHandler());
        }
    }

    public static void main(String[] args) {
        int port = 8080;
        new EchoServer().bind(port);
    }
}


EchoServerHandler:

package delimiter;


import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;

import java.util.Date;


/**
 * 对网络事件进行读写操作
 */
public class EchoServerHandler extends ChannelHandlerAdapter {

    private int counter = 0;

    /**
     * 当异常发生时
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //super.exceptionCaught(ctx, cause);
        ctx.close();
    }

    /**
     * 读取缓冲区里面的数据,处理并返回
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //super.channelRead(ctx, msg);
        String body = (String) msg;
        System.out.println("this is : " + ++counter +"times receive client : [" + body + "]");
        body +="$_";
       ByteBuf echo = Unpooled.copiedBuffer(body.getBytes());
       ctx.writeAndFlush(echo);
    }

}

EchoClient:

package delimiter;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import nettybanbao.TimeClientHandler;

/**
 * netty的客户端
 */

public class EchoClient {

    public void connect(String host, int port){

        //NioEventLoopGroup是一个线程组,它包含了一组NIO线程
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            //客户端辅助启动类
            Bootstrap b = new Bootstrap();

            //设置线程组
            b.group(group)
                    .channel(NioSocketChannel.class)//设置Channel
                    .option(ChannelOption.TCP_NODELAY, true)//设置TCP的参数
                    .handler(new ChannelInitializer<SocketChannel>() {//匿名内部类设置handler
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ByteBuf delimter = Unpooled.copiedBuffer("$_".getBytes());
                            //DelimiterBasedFrameDecoder有2个参数,
                            // 第一个参数是单条消息的最大长度,当达到该长度后还没有查找到分隔符,则抛出异常
                            //第二个参数是分隔符缓冲对象
                            socketChannel.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimter));
                            socketChannel.pipeline().addLast(new StringDecoder());
                            socketChannel.pipeline().addLast(new EchoClientHandler());
                        }
                    });
            //异步连接客户端,同步阻塞直到连接成功
        ChannelFuture f = b.connect(host, port).sync();
            //阻塞,等待客户端链路关闭后main函数才退出
        f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            group.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        String host = "127.0.0.1";
        int port = 8080;
        new EchoClient().connect(host, port);
    }
}

EchoClientHandler:

package delimiter;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;

public class EchoClientHandler extends ChannelHandlerAdapter {


    private int counter;

    static final String ECHO_REQ = "Hi, chengkui. welcome to netty.$_";

    /**
     * 初始化ByteBuf,初始化发送给服务端的消息
     */
    public EchoClientHandler(){

    }

    /**
     * 连接服务端成功后开始发送消息
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //super.channelActive(ctx);
        for(int i=0; i< 10; i++){
            ctx.writeAndFlush(Unpooled.copiedBuffer(ECHO_REQ.getBytes()));
        }

    }

    /**
     * 读取客户端的返回消息
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("this is " + ++counter +"times receive server: [" + msg +"]");
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    /**
     * 发生异常时关闭ctx
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //super.exceptionCaught(ctx, cause);
        ctx.close();
    }
}

FixedLengthFrameDecoder是一个固定长度的解码器,他按照固定的长度对消息自动解码,如果是半包消息,他会缓存半包消息并等待下个包到达后进行拼包,知道读取到一个完整的包;

EchoServer:

package fixlength;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.FixedLengthFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;

/**
 * 时间服务器,当有客户端请求时,返回服务端当前时间
 */

public class EchoServer {

    public void bind(int port){

        //NioEventLoopGroup是一个线程组,它包含了一组NIO线程,
        // 这里的两个线程组一个是用于服务端接受客户端的连接,
        // 另一个用于SocketChannel的网络读写
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            //netty用于启动NIO服务端的辅助启动类
            ServerBootstrap b = new ServerBootstrap();

            //设置线程组
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)//设置channel
                    .option(ChannelOption.SO_BACKLOG, 100)//设置channel的TCP参数
                    .childHandler(new ChildChannelHandler());//绑定IO事件处理类

            //绑定监听端口,调用同步阻塞方法等待绑定完成
            ChannelFuture f = b.bind(port).sync();
            //阻塞,等待服务端链路关闭后main函数才退出
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            //优雅退出,释放跟shutdownGracefully相关联的所有资源
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    private class ChildChannelHandler extends ChannelInitializer<SocketChannel>{

        @Override
        protected void initChannel(SocketChannel serverSocket) throws Exception {
            //FixedLengthFrameDecoder是一个固定长度的解码器,这里的长度设置为20
            serverSocket.pipeline().addLast(new FixedLengthFrameDecoder(20));
            serverSocket.pipeline().addLast(new StringDecoder());
        serverSocket.pipeline().addLast(new EchoServerHandler());
        }
    }

    public static void main(String[] args) {
        int port = 8080;
        new EchoServer().bind(port);
    }
}


EchoServerHandler:

package fixlength;


import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;


/**
 * 对网络事件进行读写操作
 */
public class EchoServerHandler extends ChannelHandlerAdapter {


    /**
     * 当异常发生时
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //super.exceptionCaught(ctx, cause);
        ctx.close();
    }

    /**
     * 读取缓冲区里面的数据,处理并返回
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("Receive client:" + msg);
    }

}

EchoClient:

package fixlength;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.FixedLengthFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;

/**
 * netty的客户端
 */

public class EchoClient {

    public void connect(String host, int port){

        //NioEventLoopGroup是一个线程组,它包含了一组NIO线程
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            //客户端辅助启动类
            Bootstrap b = new Bootstrap();

            //设置线程组
            b.group(group)
                    .channel(NioSocketChannel.class)//设置Channel
                    .option(ChannelOption.TCP_NODELAY, true)//设置TCP的参数
                    .handler(new ChannelInitializer<SocketChannel>() {//匿名内部类设置handler
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast(new FixedLengthFrameDecoder(20));
                            socketChannel.pipeline().addLast(new StringDecoder());
                            socketChannel.pipeline().addLast(new EchoClientHandler());
                        }
                    });
            //异步连接客户端,同步阻塞直到连接成功
        ChannelFuture f = b.connect(host, port).sync();
            //阻塞,等待客户端链路关闭后main函数才退出
        f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            group.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        String host = "127.0.0.1";
        int port = 8080;
        new EchoClient().connect(host, port);
    }
}

EchoClientHandler:

package fixlength;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;

public class EchoClientHandler extends ChannelHandlerAdapter {


    static final String ECHO_REQ = "Hello, chengkui weicome to netty";

    /**
     * 初始化ByteBuf,初始化发送给服务端的消息
     */
    public EchoClientHandler(){

    }

    /**
     * 连接服务端成功后开始发送消息
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
            ctx.writeAndFlush(Unpooled.copiedBuffer(ECHO_REQ.getBytes()));

    }

    /**
     * 读取客户端的返回消息
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("receive server: [" + msg +"]");
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    /**
     * 发生异常时关闭ctx
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //super.exceptionCaught(ctx, cause);
        ctx.close();
    }
}

猜你喜欢

转载自blog.csdn.net/chengkui1990/article/details/81630945