Netty入门应用之第一个netty项目
来源:互联网 发布:office mac 更新补丁 编辑:程序博客网 时间:2024/04/29 18:52
服务器端代码
public class TimeServer { public void bind(int port) throws Exception{ //创建两NioEventLoopGroup实例。 //NioEventLoopGroup是个线程组。 EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try{ //创建ServerBootstrap对象,它是Netty用于启动NIO服务端的辅助启动类,目的是降低服务端的开发复杂度。 ServerBootstrap b = new ServerBootstrap(); //调用ServerBootstrap的group方法,将两个NIO线程组当做入参传递到ServerBootstrap中。 b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 1024) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast(new TimeServerHandler()); } }); ChannelFuture f = b.bind(port).sync(); //等待服务锻炼路关闭之后main函数才退出。 f.channel().closeFuture().sync(); }finally { //优雅退出,释放线程池资源。 bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception{ int port = 8088; new TimeServer().bind(port); }}Netty服务器端Handler端代码
public class TimeServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { //类型转换:将msg转成ByteBuf对象 ByteBuf buf = (ByteBuf) msg; byte[] req = new byte[buf.readableBytes()]; buf.readBytes(req); String body = new String(req , "UTF-8"); System.out.println("The time server receive order:" + body); String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new java.util.Date( System.currentTimeMillis()).toString() : "BAD ORDER" ; ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes()); ctx.write(resp); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { // TODO Auto-generated method stub super.channelReadComplete(ctx); ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { // TODO Auto-generated method stub super.exceptionCaught(ctx, cause); ctx.close(); }}先对服务器端的代码进行一下解析:
EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup();创建两个NioEventLoopGroup实例,NioEventLoopGroup是一个线程组,专门用于网络事件的处理。
这里创建两个的原因是一个用于服务器端接受客户端的连接,另一个用于进行SocketChannel的网络读写。
ServerBootstrap b = new ServerBootstrap();创建ServerBootstrap用于启动NIO服务端的辅助启动类,目的是降低服务端的开发复杂度。
b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 1024) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast(new TimeServerHandler()); } });调用ServerBootstrap的group方法将两个NIO线程组传递到ServerBootstrap中,设置创建的channel为NioSeverSocketChannel,功能是对应JDK NIO类库中的ServerSocketChannel类。然后配置NioServerSocektChannel的TCP参数。最后绑定处理类,主要用于处理网络I/O事件。
f.channel().closeFuture().sync();阻塞方法,等待服务端链路关闭之后main函数才退出。
bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully();优雅退出,释放相关资源。
ByteBuf buf = (ByteBuf) msg; byte[] req = new byte[buf.readableBytes()]; buf.readBytes(req); String body = new String(req , "UTF-8");将msg转换成netty的ByteBuf对象。通过ByteBuf的readableBytes方法可以获取缓冲区可读字节数,根据可读字节数创建byte数组,通过ByteBuf的readBytes方法将缓冲区中的字节数组复制到新建的byte数组中。
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { // TODO Auto-generated method stub super.exceptionCaught(ctx, cause); ctx.close(); }当发生异常时,关闭ChannelHandlerContext,释放和channelHandlerContext相关联的句柄资源。
Netty客户端TimeClient
public class TimeClient { public void connent(int port , String host) throws Exception { EventLoopGroup group = new NioEventLoopGroup(); try{ Bootstrap b = new Bootstrap(); b.group(group).channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new TimeClientHandler()); } }); ChannelFuture f = b.connect(host , port).sync(); f.channel().closeFuture().sync(); }finally { group.shutdownGracefully(); } } public static void main(String[] args) throws Exception{ int port = 8088; new TimeClient().connent(port, "127.0.0.1"); }}
Netty客户端TimeClientHandler 代码
public class TimeClientHandler extends ChannelInboundHandlerAdapter { private static final Logger logger = Logger.getLogger(TimeClientHandler.class.getName()); private byte[] req ; @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { this.req = "QUERY TIME ORDER".getBytes(); ByteBuf message = Unpooled.buffer(req.length); message.writeBytes(req); 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("Now is : "+ body); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { logger.warning("Unexpected exception from downstream : "+cause.getMessage()); ctx.close(); }}重点在channelActive, channelRead 和 execptionCaught 三个方法上。当客户端和服务器端TCP链路建立成功之后,Netty的NIO线程会调用channelActive方法,发送查询指令给服务器端,调用ChannelHandlerContext的writeAndFlush方法将请求消息发送给客户端。 当服务端返回应答时,channelRead方法被调用。
阅读全文
0 0
- Netty入门应用之第一个netty项目
- Netty【二】 第一个Netty应用
- Netty权威指南之Netty入门应用
- Netty In Action 读书笔记 - 第二章 第一个Netty应用
- Netty in action—第一个Netty应用
- AAANetty入门:开发第一个Netty应用程序
- netty(七)netty入门应用
- 你的第一个Netty应用
- 第一个Netty程序
- 第一个netty应用程序
- 第一个Netty程序
- 【Netty第二章】 第一个Netty程序
- Netty入门应用
- Netty入门应用
- Netty入门应用一
- Netty入门应用
- Netty入门应用开发
- Netty4实战第二章:第一个Netty应用
- ubuntu下用过的命令 记录
- CDQZ Challenge 19
- tensorflow中的strides参数
- SCI\EI以及大学毕业论文 参考文献 在文章内的引用
- 关于json格式字符串解析并用mybatis存入数据库
- Netty入门应用之第一个netty项目
- bzoj3038 上帝造题的七分钟2(线段树区间开方统计和)
- 用Echarts制作供水工程地图迁移动画
- 中序表达式 转为 后序表达式(包含了输出运行的结果)(1310 P102)
- 网易2018校招Java开发工程师笔试卷 String.split()如何分割"|"
- 网易内推2017最长01子串
- linux 下查找文件或者内容常有命令
- A
- 算法学习之旅,初级篇(12)--最小公倍数