博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Netty】第一个Netty应用
阅读量:4582 次
发布时间:2019-06-09

本文共 8194 字,大约阅读时间需要 27 分钟。

一、前言

  前面已经学习完了Java NIO的内容,接着来学习Netty,本篇将通过一个简单的应用来了解Netty的使用。

二、Netty应用

  2.1 服务端客户端框架图

  下图展示了Netty中服务端与客户端在之间的关系,客户端连接至服务器,然后两者之间互相通信,服务器可连接多个客户端。

  

  2.2 服务端

  服务端主要包含两部分内容,分为引导和实现服务器处理器。引导用于设置端口号等信息,处理器主要是用于处理用户自定义逻辑。

  1. 引导服务端

  引导服务端类名为EchoServer,其代码如下 

import io.netty.bootstrap.ServerBootstrap;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.SocketChannel;import io.netty.channel.socket.nio.NioServerSocketChannel;import java.net.InetSocketAddress;public class EchoServer {    private int port;    public EchoServer(int port) {        this.port = port;    }    public void start() throws Exception {        EventLoopGroup group = new NioEventLoopGroup();        try {            ServerBootstrap b = new ServerBootstrap();            b.group(group)                    .channel(NioServerSocketChannel.class)                    .localAddress(new InetSocketAddress(port))                    .childHandler(new ChannelInitializer
() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new EchoServerHandler()); } }); // 绑定端口,开始接收连接 ChannelFuture f = b.bind().sync(); System.out.println("Server start listen at " + port); // 等待服务器socket关闭 f.channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port; if (args.length > 0) { port = Integer.parseInt(args[0]); } else { port = 8080; } new EchoServer(port).start(); }}

  说明:其流程大致如下

  ① 创建NioEventLoopGroup实例来处理事件,如接受连接,读写数据等。

  ② 创建ServerBootstrap实例。

  ③ 指定服务端绑定的端口。

  ④ 设置childHandler来处理每一次连接。

  ⑤ 使用ServerBootstrap的bind方法进行绑定并同步直至其完成绑定。

  2. 实现服务端逻辑

  从代码来看引导服务器只是完成了服务端的创建,如指定端口和处理器等,并未涉及到服务端的具体逻辑,其具体业务逻辑可以在处理器中完成,处理器需要继承ChannelInboundHandlerAdapter,本实例中处理器为EchoServerHandler,其代码如下 

package com.hust.grid.leesf.chapter2;import io.netty.buffer.ByteBuf;import io.netty.buffer.ByteBufUtil;import io.netty.buffer.Unpooled;import io.netty.channel.ChannelFutureListener;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInboundHandlerAdapter;public class EchoServerHandler extends ChannelInboundHandlerAdapter {    @Override    public void channelRead(ChannelHandlerContext ctx, Object msg) {        ByteBuf bb = (ByteBuf) msg;        bb.markReaderIndex();        System.out.println("Server received: " + ByteBufUtil                .hexDump(bb.readBytes(bb.readableBytes())));        bb.resetReaderIndex();        ctx.write(msg);    }    @Override    public void channelReadComplete(ChannelHandlerContext ctx) {        ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)                .addListener(ChannelFutureListener.CLOSE);    }    @Override    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {        cause.printStackTrace();        ctx.close();    }}

  说明:当服务器接受到消息后,channelRead方法会被调用,具体消息为msg,用户可以对该消息进行处理,本例中首先将接收的消息进行转化后打印,然后将消息写入ctx中,其中值得注意的是需要标记读索引,然后恢复,否则写入的数据为空。channelReadComplete将之前写入客户端的消息刷新,待操作完成后关闭。exceptionCaught方法则会捕捉处理中的异常。

  2.3 客户端

  客户端部分的逻辑同服务器类似,也包含引导客户端和实现客户端处理器两部分,客户端连接服务端,并且接收服务端的消息,关闭连接等。

  1. 引导客户端

  引导客户端类名为EchoClient,其代码如下  

package com.hust.grid.leesf.chapter2;import io.netty.bootstrap.Bootstrap;import io.netty.channel.*;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioSocketChannel;import java.net.InetSocketAddress;public final class EchoClient {    private String host;    private int port;    public EchoClient(String host, int port) {        this.host = host;        this.port = port;    }    public void start() throws Exception {        EventLoopGroup group = new NioEventLoopGroup();        try {            Bootstrap b = new Bootstrap();            b.group(group)                    .channel(NioSocketChannel.class)                    .remoteAddress(new InetSocketAddress(host, port))                    .handler(new ChannelInitializer
() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new EchoClientHandler()); } }); // 启动客户端 ChannelFuture f = b.connect().sync(); // 直到连接关闭 f.channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } public static void main(String[] args) throws Exception { String host = "127.0.0.1"; int port = 8080; if (args.length == 2) { host = args[0]; port = Integer.parseInt(args[1]); } new EchoClient(host, port).start(); }}

  说明:其引导部分与服务端非常类似,流程非常类似,其给出了服务端的地址和端口号,Bootstrap的connect函数将会根据指定的地址和端口号连接服务器。

  2. 实现客户端逻辑

  本部分完成用户实际的业务逻辑,本例中的EchoClientHandler继承SimpleChannelInboundHandler,需要重写如下三个函数

    · channelActive函数,在建立了与服务端的连接后该函数被调用。

    · channelRead0函数,当接收到服务端发送来的消息后被调用。

    · exceptionCaught函数,当处理发生异常时被调用。

  EchoClientHandler的代码如下  

package com.hust.grid.leesf.chapter2;import io.netty.buffer.ByteBuf;import io.netty.buffer.ByteBufUtil;import io.netty.buffer.Unpooled;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.SimpleChannelInboundHandler;import io.netty.util.CharsetUtil;public class EchoClientHandler extends SimpleChannelInboundHandler
{ @Override public void channelActive(ChannelHandlerContext ctx) { ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8)); } @Override public void channelRead0(ChannelHandlerContext ctx, ByteBuf in) { System.out.println("Client received: " + ByteBufUtil .hexDump(in.readBytes(in.readableBytes()))); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); }}

  说明:当同服务器的连接建立后,客户端会发送消息至服务端,然后当接收到服务端发送来的消息时,打印该消息。

  2.4 运行

  1. pom.xml文件

  由于本应用依赖的jar文件使用maven构建,其pom.xml文件如下。

4.0.0
NettyInAction
com.hust.grid.leesf
1.0-SNAPSHOT
UTF-8
2.6.3
org.apache.maven.plugins
maven-compiler-plugin
3.2
true
1.7
1.7
junit
junit
4.12
test
io.netty
netty-all
4.0.32.Final
com.fasterxml.jackson.core
jackson-core
${version.jackson.core}
com.fasterxml.jackson.core
jackson-databind
${version.jackson.core}

  2. 运行服务端

  启动EchoServer,等待客户端连接。

  3. 运行客户端

  启动EchoClient,连接服务端并发送消息。

  其中服务端的运行结果如下。  

Server start listen at 8080Server received: 4e6574747920726f636b7321

  客户端的运行结果如下。 

Client received: 4e6574747920726f636b7321

三、总结

  本篇博文讲解了Netty的简单应用,通过简单应用对Netty有所了解,具体的细节将会在之后的博文中进行讲解,本文的代码已经上传至,也谢谢各位园友的观看~ 

转载于:https://www.cnblogs.com/leesf456/p/6824345.html

你可能感兴趣的文章
子节点填充父元素除去一固定高度后的剩余高度
查看>>
[原]IOS 后台发送邮件
查看>>
(转)JAVA Calendar详解
查看>>
转: 编码,charset,乱码,unicode,utf-8与net简单释义
查看>>
C#--正则匹配
查看>>
5.30 考试修改+总结
查看>>
BA-设计施工调试流程
查看>>
C#-CLR各版本特点
查看>>
css3背景透明文字不透明
查看>>
《java JDK7 学习笔记》之接口与多态
查看>>
android的用户定位(一)
查看>>
设计模式-结构型模式,外观模式(6)
查看>>
[Java] 遍历HashMap和HashMap转换成List的两种方式
查看>>
mongodb
查看>>
LeetCode 46. Permutations
查看>>
jmeter- 性能测试3:聚合报告(Aggregate Report )
查看>>
JavaScript高级程序设计---学习笔记(二)
查看>>
vim 插件的学习
查看>>
Uncaught SyntaxError: Unexpected token ILLEGAL
查看>>
一个预处理定义的问题
查看>>