Netty权威指南之Netty入门应用

阿里 阅读:692 2021-03-31 22:29:05 评论:0

本章节需要学习的内容如下:

1、Netty开发环境搭建

2、服务端程序开发NettyServer

3、客户端程序开发NettyClient


第一节:Netty开发环境搭建

(1)、访问Netty的官网http://netty.io,从【Download】标签页下载netty-5.0.0.Alpha2.tar.bz2安装包,安装包不大,14.6M左右。下载完成后,如下截图:


(2)、通过解压缩工具打开压缩工具,如以下截图:


(3)、搭建Netty 应用工程,使用MyEclipse 10 创建普通的Java工程,同时创建Java源文件的package。


(4)、创建第三方类库存放文件夹lib,同时将netty-all-5.0.0.Alpha2.jar文件复制到lib目录下。


到此,Netty应用程序的开发环境已经搭建完毕。


第二节:Netty服务端开发

温故知新:在开始使用Netty开发服务端之前,先回顾一下使用NIO进行服务端开发步骤:

1、创建ServerSocketChannle,并配置它为非阻塞模式。

2、绑定监听,配置TCP参数。比如blocklog大小。

3、创建一个独立的IO线程,用于轮训多路复用器Selector。

4、创建Selector,将之前创建的ServerSocketChannle注册到Selector上,监听SelectKey.Accept.

5、启动IO线程,在循环体中执行Selector.select()方法,轮训就绪的Channle.

6、当轮训到就绪状态的Channle,需要对其判断,如果是SelectorKey.Accept状态,说明是新客户端接入,则调用ServerSocketChannle.accept()的方法接受新的客户端。

7、设置新接入的客户端的链路SocketChannle为非阻塞模式,配置其他的TCP参数。

8、将SocketChannle注册到Selector,监听OP_READ操作位。

9、如果轮训的Channle为OP_READ,则说明SocketChannle中有新的就绪的数据包需要读取,构造ByteBuff对象,读取数据包。

10、如果轮训的Channle的状态为OP_WRITE,说明还有数据没有发送完成,需要继续发送。


分析:一个简单的Java NIO服务端程序,如果我们选择使用Java JDK 的NIO库开发,竟然需要进过繁琐的十几步操作才能完成最基本的信息发送与接受,这也是我们选择Java NIO 开源框架的原因(Netty).

NettyServer.java

package com.nio.server; 
 
import com.nio.handler.NettyServerHandler; 
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; 
 
 
 
/** 
 * Created by vixuan-008 on 2015/6/19. 
 */ 
public class NettyServer { 
    public static void main(String[] args)throws Exception{ 
        int port=17666; 
        new NettyServer().bind(port); 
 
 
    } 
    public void bind(int port)throws Exception{ 
        //配置服务端的NIO线程池 
        EventLoopGroup bossGroup=new NioEventLoopGroup(); 
        EventLoopGroup workGroup=new NioEventLoopGroup(); 
        try{ 
            ServerBootstrap b=new ServerBootstrap(); 
            b.group(bossGroup,workGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG,1024).childHandler(new NettyServerHandler()); 
            //绑定端口,等待同步成功 
            ChannelFuture f=b.bind(port).sync(); 
            //等待服务端关闭监听端口 
            f.channel().closeFuture().sync(); 
 
        }finally { 
            //释放线程池资源 
            bossGroup.shutdownGracefully(); 
            workGroup.shutdownGracefully(); 
 
        } 
 
 
    } 
    //添加内部类 
    private class ChildChannelHandler extends ChannelInitializer<SocketChannel>{ 
        @Override 
        protected void initChannel(SocketChannel socketChannel) throws Exception { 
            socketChannel.pipeline().addLast(new NettyServerHandler()); 
 
        } 
    } 
 
} 
NettyServerHandler.java

package com.nio.handler; 
 
import io.netty.buffer.ByteBuf; 
import io.netty.buffer.Unpooled; 
import io.netty.channel.ChannelHandlerAdapter; 
import io.netty.channel.ChannelHandlerContext; 
 
 
 
 
/** 
 * Created by vixuan-008 on 2015/6/19. 
 */ 
public class NettyServerHandler extends ChannelHandlerAdapter { 
    @Override 
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 
            ctx.close(); 
    } 
 
    @Override 
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 
        ByteBuf buf=(ByteBuf)msg; 
        byte[] req=new byte[buf.readableBytes()]; 
        buf.readBytes(req); 
        String body=new String(req,"UTF-8"); 
        System.out.println("the server receiver data is:"+body); 
        String currentTime="time".equalsIgnoreCase(body) ? new java.util.Date(System.currentTimeMillis()).toString():"no zuo no die"; 
        ByteBuf resp= Unpooled.copiedBuffer(currentTime.getBytes()); 
        ctx.write(resp); 
    } 
 
    @Override 
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { 
        super.channelReadComplete(ctx); 
        ctx.flush(); 
    } 
} 






第三节:Netty客户端开发

NettyClient.java

package com.nio.client; 
 
import com.nio.handler.NettyClientHandler; 
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; 
 
 
 
 
/** 
 * Created by vixuan-008 on 2015/6/19. 
 */ 
public class NettyClient { 
    public static void main(String[] args)throws  Exception{ 
        int port=17666; 
        new NettyClient().connect(port,"127.0.0.1"); 
 
    } 
 
    public void connect(int port,String host)throws Exception{ 
        //配置客户端NIO线程池 
        EventLoopGroup workGroup=new NioEventLoopGroup(); 
        try{ 
            io.netty.bootstrap.Bootstrap b=new io.netty.bootstrap.Bootstrap(); 
            b.group(workGroup).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY,true).handler(new ChannelInitializer<SocketChannel>() { 
                @Override 
                protected void initChannel(SocketChannel socketChannel) throws Exception { 
                    socketChannel.pipeline().addLast(new NettyClientHandler()); 
                } 
            }); 
            //发起异步连接操作 
            ChannelFuture f=b.connect(host,port).sync(); 
            //等待客户端链路关闭 
            f.channel().closeFuture().sync(); 
 
        }finally { 
            //释放NIO 线程组 
            workGroup.shutdownGracefully(); 
 
        } 
    } 
 
 
} 

NettyClientHandler.java

package com.nio.handler; 
 
import io.netty.buffer.ByteBuf; 
import io.netty.buffer.Unpooled; 
import io.netty.channel.ChannelHandlerAdapter; 
import io.netty.channel.ChannelHandlerContext; 
 
/** 
 * Created by vixuan-008 on 2015/6/19. 
 */ 
public class NettyClientHandler extends ChannelHandlerAdapter { 
    private final ByteBuf message; 
 
    public NettyClientHandler() { 
        byte[] req="time".getBytes(); 
        message= Unpooled.buffer(req.length); 
        message.writeBytes(req); 
    } 
 
    @Override 
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 
 
        ctx.close(); 
    } 
 
    @Override 
    public void channelActive(ChannelHandlerContext ctx) throws Exception { 
 
        ctx.writeAndFlush(message); 
    } 
 
    @Override 
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 
 
        ByteBuf buf=(ByteBuf)msg; 
        byte[] req=new byte[buf.readableBytes()]; 
        buf.readBytes(req); 
        String body=new String(req,"UTF-8"); 
        System.out.println("this client receiver data is:"+body); 
    } 
 
    @Override 
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { 
 
    } 
} 


今天学习到此结束。

:

声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号