共计 4948 个字符,预计需要花费 13 分钟才能阅读完成。
作者:rickiyang
出处:www.cnblogs.com/rickiyang/p/11074237.html
这一节咱们来解说 Netty,应用 Netty 之前咱们先理解一下 Netty 能做什么,有为而学,岂不是白费力气!
1. 应用 Netty 可能做什么
- 开发异步、非阻塞的 TCP 网络应用程序;
- 开发异步、非阻塞的 UDP 网络应用程序;
- 开发异步文件传输应用程序;
- 开发异步 HTTP 服务端和客户端应用程序;
- 提供对多种编解码框架的集成,包含谷歌的 Protobuf、Jboss marshalling、Java 序列化、压缩编解码、XML 解码、字符串编解码等,这些编解码框架能够被用户间接应用;
- 提供形式多样的编解码根底类库,能够十分不便的实现公有协定栈编解码框架的二次定制和开发;
- 基于职责链模式的 Pipeline-Handler 机制,用户能够十分不便的对网络事件进行拦挡和定制;
- 所有的 IO 操作都是异步的,用户能够通过 Future-Listener 机制被动 Get 后果或者由 IO 线程操作实现之后被动 Notify 后果,用户的业务线程不须要同步期待;
- IP 黑白名单管制;
- 打印消息码流;
- 流量管制和整形;
- 性能统计;
- 基于链路闲暇事件检测的心跳检测
2. Netty 罕用类解说
在这里咱们就一些咱们罕用到的类做大抵的解说,而后再写入门程序的时候大抵晓得每一行都讲了什么。
EventLoop,EventLoopGroup
EventLoop 目标是为 Channel 解决 IO 操作,一个 EventLoop 能够为多个 Channel 服务,EventLoopGroup 会蕴含多个 EventLoop。
BootStrap,ServerBootstrap
一个 Netty 利用通常由一个 Bootstrap 开始,它次要作用是配置整个 Netty 程序,串联起各个组件。
ChannelInitializer
当一个链接建设时,咱们须要晓得怎么来接管或者发送数据,当然,咱们有各种各样的 Handler 实现来解决它,那么 ChannelInitializer 便是用来配置这些 Handler,它会提供一个 ChannelPipeline,并把 Handler 退出到 ChannelPipeline。
Handler
为了反对各种协定和解决数据的形式,便诞生了 Handler 组件。Handler 次要用来解决各种事件,这里的事件很宽泛,比方能够是连贯、数据接管、异样、数据转换等。
ChannelInboundHandler
一个最罕用的 Handler。这个 Handler 的作用就是解决接管到数据时的事件,也就是说,咱们的业务逻辑个别就是写在这个 Handler 外面的,ChannelInboundHandler 就是用来解决咱们的外围业务逻辑。
Future
在 Netty 中所有的 IO 操作都是异步的,因而,你不能立即得悉音讯是否被正确处理,然而咱们能够过一会等它执行实现或者间接注册一个监听,具体的实现就是通过 Future 和 ChannelFutures, 他们能够注册一个监听,当操作执行胜利或失败时监听会主动触发。总之,所有的操作都会返回一个 ChannelFuture。
3. 第一个 Helloworld
下面咱们曾经对罕用类进行阐明,上面咱们就应用这些类来构建咱们的第一个入门程序,本示例我应用的是 maven 来构建工程,如果你应用的是一般的我的项目则跳过第一步。
首先引入 maven jar 包:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.5.Final</version>
</dependency>
上面咱们来写客户端:
public class HelloWorldClient {
private int port;
private String address;
public HelloWorldClient(int port,String address) {
this.port = port;
this.address = address;
}
public void start(){EventLoopGroup group = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.handler(new ClientChannelInitializer());
try {Channel channel = bootstrap.connect(address,port).sync().channel();
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
for(;;){String msg = reader.readLine();
if(msg == null){continue;}
channel.writeAndFlush(msg + "\r\n");
}
} catch (Exception e) {e.printStackTrace();
}finally {group.shutdownGracefully();
}
}
public static void main(String[] args) {HelloWorldClient client = new HelloWorldClient(7788,"127.0.0.1");
client.start();}
}
ChannelInitializer 用来配置解决数据的 handler:
public class ClientChannelInitializer extends ChannelInitializer<SocketChannel> {protected void initChannel(SocketChannel socketChannel) throws Exception {ChannelPipeline pipeline = socketChannel.pipeline();
/*
* 这个中央的 必须和服务端对应上。否则无奈失常解码和编码
*
* 解码和编码 我将会在下一节为大家具体的解说。临时不做具体的形容
*
* /
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
// 咱们本人的 handler
pipeline.addLast("handler", new HelloWorldClientHandler());
}
}
写一个咱们本人的 handler,用本人的形式来解决数据:
public class HelloWorldClientHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {System.out.println("server say :"+msg.toString());
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println("Client is active");
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {System.out.println("Client is close");
}
}
客户端咱们写完了,上面开始写服务器端:
public class HelloWordServer {
private int port;
public HelloWordServer(int port) {this.port = port;}
public void start(){EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workGroup = new NioEventLoopGroup();
ServerBootstrap server = new ServerBootstrap().group(bossGroup,workGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ServerChannelInitializer());
try {ChannelFuture future = server.bind(port).sync();
future.channel().closeFuture().sync();} catch (InterruptedException e) {e.printStackTrace();
}finally {bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();}
}
public static void main(String[] args) {HelloWordServer server = new HelloWordServer(7788);
server.start();}
}
服务端的 ChannelInitializer:
public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {ChannelPipeline pipeline = socketChannel.pipeline();
// 字符串解码 和 编码
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
// 本人的逻辑 Handler
pipeline.addLast("handler", new HelloWordServerHandler());
}
}
服务器端的 handler:
public class HelloWordServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {System.out.println(ctx.channel().remoteAddress()+"===>server:"+msg.toString());
ctx.write("received your msg");
ctx.flush();}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {super.exceptionCaught(ctx, cause);
ctx.close();}
}
下面服务器端和客户端的代码都曾经写完,上面咱们先启动服务端,而后启动客户端,程序中我是在客户端让手动输出,输出完结之后回车,服务器端即可承受数据。
客户端:
服务端:
近期热文举荐:
1.1,000+ 道 Java 面试题及答案整顿 (2021 最新版)
2. 终于靠开源我的项目弄到 IntelliJ IDEA 激活码了,真香!
3. 阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!
4.Spring Cloud 2020.0.0 正式公布,全新颠覆性版本!
5.《Java 开发手册(嵩山版)》最新公布,速速下载!
感觉不错,别忘了顺手点赞 + 转发哦!