作者: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開發手冊(嵩山版)》最新發布,速速下載!
覺得不錯,別忘了隨手點贊+轉發哦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/288909.html
標籤:其他
上一篇:Python基礎之GUI編程
