netty入门

一。用netty创建server

  

package com.cw.demo.netty.server;

import com.cw.demo.netty.server.channelhandler.EchoServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;


/**
 * @author  chenwei
 * Created by chenwei01 on 2017/4/24.
 * 1.创建ServerBootstrap实例来引导绑定和启动服务器
 * 2.创建NioEventLoopGroup对象来处理事件,如接受新连接、接收数据、写数据等等
 * 3.指定InetSocketAddress,服务器监听此端口
 * 4.设置childHandler执行所有的连接请求
 * 5.都设置完毕了,最后调用ServerBootstrap.bind() 方法来绑定服务器
 */
public class EchoServer {

    private  int port;

    public EchoServer(int port){
        this.port=port;
    }

    public void start() throws  Exception{
        //因为使用NIO,指定NioEventLoopGroup来接受和处理新连接
        EventLoopGroup group = new NioEventLoopGroup();
        //创建bootstrap来启动服务器
        ServerBootstrap boot = new ServerBootstrap();
        boot.group(group).
                //指定通道类型为NioServerSocketChannel
                        channel(NioServerSocketChannel.class).
                        localAddress(port).
                   //调用childHandler用来指定连接后调用的ChannelHandler
                        childHandler(new ChannelInitializer<Channel>() {
                       //这个方法传ChannelInitializer类型的参数,ChannelInitializer是个抽象类,所以需要实现initChannel方法,这个方法就是用来设置ChannelHandler
                       @Override
                       protected void initChannel(Channel channel) throws Exception {
                           channel.pipeline().addLast(new EchoServerHandler());
                       }
                   });
        ChannelFuture future=boot.bind().sync();
        System.out.println( EchoServer.class.getName()+" started and listen on "+future.channel().localAddress());
        future.channel().closeFuture().sync();


    }


    public static void main(String[] args) {
        EchoServer server=new EchoServer(20000);
        try {
            server.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

创建 ChannelHandler,实际上 ChannelHandler 处理实际业务的主要代码

package com.cw.demo.netty.server.channelhandler;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;

import java.nio.charset.Charset;
/**
 *   Netty中有两个方向的数据流,上图显示的入站(ChannelInboundHandler)和出站(ChannelOutboundHandler)之间有一个明显的区别:
 *   若数据是从用户应用程序到远程主机则是“出站(outbound)”,
 *   相反若数据时从远程主机到用户应用程序则是“入站(inbound)”。
 *   为了使数据从一端到达另一端,一个或多个ChannelHandler将以某种方式操作数据。
 *   这些ChannelHandler会在程序的“引导”阶段被添加ChannelPipeline中,并且被添加的顺序将决定处理数据的顺序。
 *   ChannelPipeline的作用我们可以理解为用来管理ChannelHandler的一个容器,每个ChannelHandler处理各自的数据(例如入站数据只能由ChannelInboundHandler处理),
 *   处理完成后将转换的数据放到ChannelPipeline中交给下一个ChannelHandler继续处理,直到最后一个ChannelHandler处理完成。
 */

/**
 * @author  chenwei
 * Created by chenwei01 on 2017/4/25.
 *  Netty使用多个Channel Handler来对事件处理的分离,因为可以很容的添加、更新、删除业务逻辑处理handler
 *  它的每个方法都可以被重写,它的所有的方法中只有channelRead方法是必须要重写的。
 */
public class EchoServerHandler extends ChannelInboundHandlerAdapter {



    //重写该方法,该方法会被调用用来接收数据
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("Server reveived: " + ((ByteBuf) msg).toString(Charset.forName("UTF-8")));
        Channel channel = ctx.channel();

        channel.writeAndFlush(Unpooled.buffer().writeBytes("我收到了".getBytes("UTF-8")));
        ReferenceCountUtil.release(msg);
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();

    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {


    }

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

二。客户端测试

  客户端代码与服务端代码大致类似,不过是启动类用了 Bootstrap 而不是 ServerBootstrap

  或者最简单的,用telnet 来测试 刚才写的nettyServer

  

原文地址:https://www.cnblogs.com/manmanrenshenglu/p/9013346.html