|
Netty是一個(gè)異步事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用程序框架,用于快速開發(fā)可維護(hù)的高性能服務(wù)器和客戶端。它是一個(gè)NIO客戶機(jī)服務(wù)器框架,支持快速、簡單地開發(fā)網(wǎng)絡(luò)應(yīng)用程序,如服務(wù)器和客戶機(jī)。Netty大大簡化了網(wǎng)絡(luò)編程,如TCP和UDP套接字服務(wù)器。 但很多學(xué)員都向小開反應(yīng),一直在學(xué)Netty,但不得其法,學(xué)習(xí)的進(jìn)度很慢。4月27日的《HelloWorld公開課》就是為了解決你的這個(gè)問題,跟著宏彪老師,一節(jié)課讓你搞懂Netty。 Netty核心概念在正式開始Netty學(xué)習(xí)前,我們先來了解幾個(gè)Netty框架中的核心概念,Channel(管道),其是對(duì)Socket的封裝,其包含了一組API,大大簡化了直接與Socket進(jìn)行操作的復(fù)雜性。 EventLoopGroup是一個(gè)EventLoop池,包含很多的EventLoop。Netty為每個(gè)Channel分配了一個(gè)EventLoop,用于處理用戶連接請(qǐng)求、對(duì)用戶請(qǐng)求的處理等所有事件。EventLoop本身只是一個(gè)線程驅(qū)動(dòng)在其生命周期內(nèi)只會(huì)綁定一個(gè)線程,讓該線程處理一個(gè)Channel的所有IO事件。 ServerBootstrap用于配置整個(gè)Netty代碼,將各個(gè)組件關(guān)聯(lián)起來。服務(wù)端使用的是ServerBootstrap,而客戶端使用的是則Bootstrap。 ChannelHandler是對(duì)Channel中數(shù)據(jù)的處理器,這些處理器可以是系統(tǒng)本身定義好的編 解碼器,也可以是用戶自定義的。這些處理器會(huì)被統(tǒng)一添加到一個(gè)ChannelPipeline的對(duì)象中,然后按照添加的順序?qū)hannel中的數(shù)據(jù)進(jìn)行依次處理。 Netty中所有的I/O操作都是異步的,即操作不會(huì)立即得到返回結(jié)果,所以Netty中定義了一個(gè)ChannelFuture對(duì)象作為這個(gè)異步操作的“代言人”,表示異步操作本身。 如果想獲取到該異步操作的返回值,可以通過該異步操作對(duì)象的addListener()方法為該異步操作添加監(jiān)聽器,為其注冊(cè)回調(diào):當(dāng)結(jié)果出來后馬上調(diào)用執(zhí)行。Netty的異步編程模型都是建立在Future與回調(diào)概念之上的。
Scoket編程定義服務(wù)端啟動(dòng)類 public class SomeServer { public static void main(String[] args) { // 創(chuàng)建一個(gè)group,用于處理客戶端連接請(qǐng)求
NioEventLoopGroup parentGroup = new NioEventLoopGroup(); // 創(chuàng)建一個(gè)group,用于處理客戶端連接上server后的后續(xù)請(qǐng)求
NioEventLoopGroup childGroup = new NioEventLoopGroup(); try { // bootstrap用于初始化channel
ServerBootstrap bootstrap = new ServerBootstrap(); // 指定要使用的兩個(gè)group
bootstrap.group(parentGroup, childGroup) // 指定要?jiǎng)?chuàng)建的channel的類型
.channel(NioServerSocketChannel.class) // 指定要使用的處理器
.childHandler(new ChannelInitializer<SocketChannel>() { // 初始化channel的方法
@Override
protected void initChannel(SocketChannel ch)
throws Exception { // channel一旦創(chuàng)建完畢,其就會(huì)同時(shí)綁定一個(gè)pipeline
ChannelPipeline pipeline = ch.pipeline(); // 添加編碼器
pipeline.addLast(new StringEncoder()); // 添加解碼器
pipeline.addLast(new StringDecoder()); // 添加自定義的處理器
pipeline.addLast(new SomeServerHandler());
}
}); // 創(chuàng)建channel,綁定到指定的主機(jī)(hostName,port)
// sync()是將異步變同步
ChannelFuture future = bootstrap.bind(8888).sync();
System.out.println("服務(wù)器8888已經(jīng)啟動(dòng)。。。"); // 當(dāng)channel被關(guān)閉后,會(huì)觸發(fā)closeFuture()的執(zhí)行,去完成一些收尾工
作
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally { // 將兩個(gè)group進(jìn)行優(yōu)雅關(guān)閉
parentGroup.shutdownGracefully();
childGroup.shutdownGracefully();
}
}
}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748復(fù)制代碼類型:[java]定義服務(wù)端處理器 // 自定義服務(wù)端處理器,用于處理來自于客戶端的數(shù)據(jù)public class SomeServerHandler extends ChannelInboundHandlerAdapter { // 一種回調(diào)方法:當(dāng)client將數(shù)據(jù)寫入到channel并發(fā)送到server后,server端就會(huì)觸發(fā)該方法的執(zhí)行
/**
*
* @param ctx 其代表當(dāng)前處理器(其實(shí)它是當(dāng)前處理器所封裝的一個(gè)節(jié)點(diǎn))
* @param msg 就是client端發(fā)送來的數(shù)據(jù)
* @throws Exception
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception { // 輸出client的地址與發(fā)送來的數(shù)據(jù)
System.out.println(ctx.channel().remoteAddress() + ", " + msg); // 向client發(fā)送一個(gè)隨機(jī)的UUID
ctx.channel().writeAndFlush("from server: " + UUID.randomUUID());
TimeUnit.MILLISECONDS.sleep(500);
} // 一旦在服務(wù)端發(fā)生異常,就會(huì)觸發(fā)該方法的執(zhí)行
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable
cause) throws Exception {
cause.printStackTrace(); // 關(guān)閉channel
ctx.close();
}
}12345678910111213141516171819202122232425262728293031復(fù)制代碼類型:[java]Netty實(shí)現(xiàn)HTTP請(qǐng)求處理首先定義服務(wù)器啟動(dòng)類,該服務(wù)器用于創(chuàng)建并初始化服務(wù)器啟動(dòng)對(duì)象ServerBootStrap。 public class HttpServer { public static void main(String[] args)
throws InterruptedException {
EventLoopGroup parentGroup = new NioEventLoopGroup();
EventLoopGroup childGroup = new NioEventLoopGroup(); try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(parentGroup, childGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new HttpChannelInitializer());
ChannelFuture future = bootstrap.bind(8888).sync();
System.out.println("服務(wù)器啟動(dòng)了,端口號(hào)8888");
future.channel().closeFuture().sync();
} finally {
parentGroup.shutdownGracefully();
childGroup.shutdownGracefully();
}
}
}1234567891011121314151617181920212223復(fù)制代碼類型:[java]定義管道初始化器 public class HttpChannelInitializer
extends ChannelInitializer<SocketChannel> { @Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new HttpServerHandler());
}
}123456789復(fù)制代碼類型:[java]
講師介紹宏彪老師,原百度好看架構(gòu)師,現(xiàn)滬智科技技術(shù)合伙人 《Hello,World公開課》是由開課吧推出的面向廣大開發(fā)工程師的免費(fèi)加餐課,集結(jié)業(yè)內(nèi)名師大咖,聚焦熱門技術(shù)和實(shí)戰(zhàn)解決方案,以專業(yè)知識(shí)分享交流為橋梁,鏈接正在創(chuàng)造世界的一群科技主力們,向初心致敬,為技術(shù)發(fā)燒。無論你是初入職場的應(yīng)屆生,還是準(zhǔn)備升職加薪的職場精英,相信這里都有你需要的養(yǎng)料。 |
|
|