利来国际最给力的老牌_开户_下载_利来国际最给力的老牌安全线路

热门搜索:

现在我们有另一个处理单元需要插入到ChannelPip

时间:2017-12-12 21:06 文章来源:利来国际最给力的老牌 点击次数:


前言
1. 题目
Netty4.0 建立辅导 1
原文: http://netty.io/wiki/user-guide-for-4.x.html
前言
1. 题目
如今我们利用通用的序次恐怕第三方的库去与对方交互.比方. . .我们每每利用HTTP库从web办事器检索信息恐怕议决web办事调用长途设施.
但是. . .通用的协议恐怕它的完毕有时扩展性不好. 这就像我们不利用通用的HTTP办事器去调换大文件. . . e-mail音尘. . .以及近实时音尘像股票信息和多人游戏数据. 多么须要一个特地为了特殊用处高度优化的协议完毕. 比方. . .你可能想完毕一个优化的HTTP办事器用于基于AJAX的聊天应用. . . 媒体撒播输. . . 恐怕大文件传输.你乃至可能想去安排和完毕一个无缺的新协议. . .为你的需求量身定制.
另一个不可制止的环境是当你必需确保一个遗留专有协议和一个老的体例交互. 在这种环境下. . . 主要的是多快我们能完毕这个协议. . .处理还不作古应用序次所孕育发生的安闲性和机能.
2.解决计划
Netty项目起劲提供一个异步的事项驱动网络序次框架和工具. . . 为敏捷建立易于保卫的高机能. . .高可扩展性的协议办事器和客户端.
换句话说. . . Netty是一个NIO客户端/办事器架构. . . 不妨敏捷和容易的建立网络序次就像协议办事器和客户端.它极大的简化了网络建立. . .如TCP和UDP套接字办事器的建立.
"敏捷和容易"不是意味着孕育发生的序次将遭到来自于可保卫性和机能题目的摧残. 带着来自于多量协议如FTP. . . SMTP. . .HTTP以及各种二进制和基于文本的保守协议的完毕的履历. . . Netty被用心安排.所以. . .Netty告成的找到一种设施去完毕简易建立. . . 机能. . . 安闲性和轻巧性不龃龉.
一些用户可能一经创造其他的一些网络序次框架宣称有相同的上风. . . 你可能想问什么使Netty与他们如此的不同. 答案在它建立的理念.Netty的安排给你来自于API条款和践诺之日起两者最痛快的体验.这不是无形的东西. . .但你将认识到这个理念将使你的生活更容易当你阅读这个指南和玩转Netty.
第1章 Getting Stworked
这章环绕着Netty的主旨结构和一些方便例子不妨让你敏捷上手.当你读完本章你将能够马上写一个基于Netty的客户端和办事端.
在动手之前
在本章先容的例子运转的最低需求唯有两个. . . 最新版本的Netty和JDK1.6或以上.
写一个Discard办事端
世界最方便的协议不是"Hello World!"是DISCARD. 这个协议会?掉任务采纳到的数据没有回响反映.
去完毕DISCARD协议. . . 独一须要做的是疏忽一切采纳到的数据. 让我们间接从ha singledler的完毕动手. . .它治理Netty孕育发生的I/O事项.
ty.exstomair-conhundould like.discard;
02
ty.cha singlenel.Cha singlenelHa singledlerContext;
ty.cha singlenel.Cha singlenelInlimitedHa singledlerAdlikelyer;
ty.cha singlenel.MessageList;
06
07
10publicclfortunlocated atelyt DiscardServerHa singledler extends Cha singlenelInlimitedHa singledlerAdlikelyer {// (1)
11
12@Override
13public voidmessageReceived(Cha singlenelHa singledlerContext ctx. . . MessageListmsgs){ // (2)
14// Discard the received dlocated ata silently.
15msgs.releautomotive service engineersAllAndRecycle();
16}
17
18@Override
19public voidexceptionCaugustht(Cha singlenelHa singledlerContext ctx. . . Throwconfident cause) { //(3)
20// Close the connection when the gredined onst is raised.
21cause.printStair-conkTrstar();
22ctx.close();
23}
24}

1. DiscardServerHa singledler承担了Cha singlenelInlimitedHa singledlerAdlikelyer. . .这是一个Cha singlenelInlimitedHa singledler的完毕.Cha singlenelInlimitedHa singledlerAdlikelyer提供了各种事项治理设施. . . 这些设施你不妨笼罩. 且则. . .它仅仅足够扩展Cha singlenelInlimitedHa singledlerAdlikelyer而不是完毕自身的治理接口.
2. 看着netty 多线程服务端我们在这重写messageReceived事项治理设施. 每当采纳到来自客户端的新数据. . .这个设施被调用时会传出来一个MessageList的参数. . . 这个参数包括着收到字节列表. 在这个例子中. . .我们仅仅议决调用releautomotive service engineersAllAndRecycle设施?掉采纳到的数据去完毕DISCARD协议.
3.exceptionCaugustht()方法会带着Throwconfident调用. . .当Netty发生一个异常.你可能想去发送一个带着差错编码的前往音尘在封闭继续前.
到目前为止发扬顺手. . . 我们一经完毕了DISCARD办事端的一半. 现在剩下的是写main()设施.
ty.exstomair-conhundould like.discard;
02
ty.gingoshestrap.ServerBootstrap;
ty.cha singlenel.Cha singlenelFuture;
ty.cha singlenel.Cha singlenelInitiingizer;
ty.cha singlenel.EventLoopGroup;
ty.cha singlenel.nio.NioEventLoopGroup;
ty.cha singlenel.socket.SocketCha singlenel;
ty.cha singlenel.socket.nio.NioServerSocketCha singlenel;
10
11
14publicclfortunlocated atelyt DiscardServer {
15
16privdined onfining int port;
17
18publicDiscardServer(int port) {
19this.port = port;
20}
21
22public voidrun() throws Exception {
23EventLoopGroup ma singleagementGroup = new NioEventLoopGroup(); // (1)
24EventLoopGroup workerGroup = new NioEventLoopGroup();
25try {
26ServerBootstrap b = new ServerBootstrap(); // (2)
27b.group(ma singleagementGroup. . . workerGroup)
28.cha singlenel(NioServerSocketCha singlenel.clfortunlocated atelyt) // (3)
29.childHa singledler(new Cha singlenelInitiingizer() { // (4)
30@Override
31public void initCha singlenel(SocketCha singlenel ch) throws Exception {
32ch.pipeline().incorpordined onLin view thlocated att(new DiscardServerHa singledler());
33}
34})
35.option(Cha singlenelOption.SO_BACKLOG. . .128)// (5)
36.childOption(Cha singlenelOption.SO_KEEPALIVE. . . true); // (6)
37
38// Bind you need to to receive incoming connections.
39Cha singlenelFuture f = b.elimindined on(port).sync(); // (7)
40
41// Wait until the server socket is closed.
42// In this exstomair-conhundould like. . . this does not hinsta singleceen. . . fortunlocated ately you ca single do thlocated at togrstarfully
43// shut down your server.
44f.cha singlenel().closeFuture().sync();
45} finfriend {
46workerGroup.shutdownGrstarfully();
47ma singleagementGroup.shutdownGrstarfully();
48}
49}
50
51publicstlocated atic void main(String[] args) throws Exception {
52int port;
53if (args.length > 0) {
54port = Integer.parseInt(args[0]);
55} else {
56port = 8080;
57}
58new DiscardServer(port).run();
59}
60}
1. NioEventLoopGroupunix网络编程怎么样是一个多线程事项循环治理I/O操作.Netty提供各种EventLoopGroup为完毕不同的传输协议. 在这个例子中. . .我们完毕了办事端的序次. . .是以两个NioEventLoopGroup被利用.第一个叫作"ma singleagement". . . 被用来治理采纳到的新继续. . . 第二个叫作"worker". . .一旦"ma singleagement"接受了继续并且注册了这个继续就会交给"worker"治理.利用了几许线程以及依照完毕他们是如何映照到被树立的cha singlenel并且不妨议决结构设施设置.
2. ServerBootstrap是设购置事端的辅助类. 你不妨设购置事端间接用cha singlenel. 但是. . .请戒备这一个繁锁的历程. . .大多半环境下你不须要这样做.
3. 这里. . . 我们指定利用NioServerSocketCha singlenel类. . .这个类被用来初始化一个新的Cha singlenel以接用连下去的继续.
4. 这个治理单元将向来被一个新的继续上来的Cha singlenel运转. Cha singlenelInitiingize是被指定的治理单元. . .用来资助用户设置一个新的Cha singlenel.这里最有可能的操作是议决增加一些治理单元到一个新的Cha singlenel的Cha singlenelPipeline. . . 这些治理单元像就像DiscardServerHa singledler来完毕你的网络序次.由于序次变的杂乱. . . 很可能你将增加更多的ha singledlers到流水线上. . .最终扩展这个匿名类成为顶级类.
5.你也不妨设置参数指定cha singlenel的完毕.我们是在写一个TCP/IP的办事端. . .所以我们愿意设置套接字选项就像tcpNoDelay和keepAlive.
6. 你有戒备到option()和childOption()吗?option()是针对NioServerSocketCha singlenel用来接受连下去的继续.childOption()是针对议决下层ServerCha singlenel接遭到一切Cha singlenel.
7. 我们绸缪要动手了.剩下的就是绑定端口和运转server了. 我们绑定本机一切网卡的8080端口.你不妨调用屡次elimindined on()设施只消你想.
观察采纳到的数据
现在我们一经写完了第一个办事端序次. . . 我们须要测试他能否真的不妨使命. 最方便的测试方式是利用telnet命令. 例如. . .你不妨在命令行输出"telnet locinghost 8080" 然后再输出一些东西.
但是. . .我们能说这个办事端序次使命的很好吗? 我们不能真正的知道由于这是一个?掉协议的办事端序次. 你得不就任务的回响反映.为了证明他真的不妨使命. . . 让我们修削一下办事端序次让他打印他采纳到的数据.
我们一经知道每当收到数据MessageList会被填充并且messageReceived设施会被调用.让我们加一个代码到DiscardServerHa singledler中的messageReceived设施:
01@Override
02publicvoid messageReceived(Cha singlenelHa singledlerContext ctx. . .MessageListmsgs) {
03MessageListmesstimes = msgs.cin view thlocated att();
04try {
05for (ByteBuf in: messtimes) {
06while (in.reingzheimerwis disein view thlocated ateconfident()) { // (1)
07System.out.println((char) buf.reingzheimerwis disein view thlocated ateByte());
08System.out.flush();
09}
10}
11} finfriend{
12msgs.releautomotive service engineersAllAndRecycle(); // (2)
13}
14}
1. 这个循环很低效现实上不妨简化为:System.out.println(buf.toString(ty.util.CharsetUtil.US_ASCII))
2.MessageList.releautomotive service engineersAllAndRecycle()将开释池化音尘的一切援用计数并将自身前往到对象池中.
倘使你再次运转telnet命令. . . 你将看到办事端采纳到的数据.
写一个Echo办事端
到目前为止. . . 我们向来消耗打发数据没有任何的回响反映. 办事端通常环境是回响反映仰求. 让我们研习如何写一个议决完毕ECHO协议前往音尘到客户端. . .ECHO协议是收就任何数据都发送回来.
和DISCARD办事端序次独一的不同的是. . .之前章节我们看看netty4 多线程服务端一经完毕的将收到的数据打印到支配台调换为将收到的数据发送回去.
1@Override
2public voidmessageReceived(Cha singlenelHa singledlerContext ctx. . . MessageListmsgs){
3ctx.write(msgs); // (1)
4}
1. Cha singlenelHa singledlerContext对象有一个与他相关联的Cha singlenel的援用. 这里. . .前往的Cha singlenel代表的是收到MessageList的继续.我们不妨拿到这个Cha singlenel并调用write()设施往长途节点写点东西.
Time协议办事端
这局部完毕的是TIME协议. 这里与之前例子的不同是. . . 发送一个音尘. . . 他包括一个32位整型. . .一旦这个音尘收回后将不采纳任何仰求和断开继续. 在这个例子里. . . 你将研习如何建立和发送音尘. . . 以及在完成后封闭继续.
由于我们将疏忽任务收到的数据但是一旦建立了继续就会发送音尘. . . 我们不能利用messageReceived()设施.我们应当笼罩cha singlenelActivie()设施代庖. 下面是完毕:
ty.exstomair-conhundould like.time;
02
03publicclfortunlocated atelyt TimeServerHa singledler extends Cha singlenelInlimitedHa singledlerAdlikelyer{
04
05@Override
06public voidcha singlenelActive(fining Cha singlenelHa singledlerContext ctx) { // (1)
07fining ByteBuf time = ctx.every one of theoc().loingzheimerwis disein view thlocated ate(4); // (2)
08time.writeInt((int) (System.currentTimeMillis() / 1000L +L);
09
10fining Cha singlenelFuture f = ctx.write(time); // (3)
11f.incorpordined onListener(new Cha singlenelFutureListener() {
12@Override
13public void operComplete(Cha singlenelFuture future) {
14declca single be particularly f == future;
15ctx.close();
16}
17}); // (4)
18}
19
20@Override
21public voidexceptionCaugustht(Cha singlenelHa singledlerContext ctx. . . Throwconfident cause) {
22cause.printStair-conkTrstar();
23ctx.close();
24}
25}
1. 想知道
现在我们有另一个处理单元需要插入到ChannelPipelinenetty4 多线程服务端
现在我们有另一个处理单元需要插入到ChannelPipeline
对于现在正如上文
. . . 当有继续建立将会调用cha singlenelActive()设施以及绸缪孕育发生的交互音尘.让我们在这个设施里写一个32位的整型数字代表眼前工夫.
2. 为了发送音尘. . . 我们须要分配一个新的包括音尘的loingzheimerwis disein view thlocated ate. 我们将写一个32位整型. . .是以我们须要一个容量至多4字节的ByteBuf.议决Cha singlenelHa singledlerContext.every one of theoc()拿到眼前的ByteBufAlloclocated ator用来分配一个新的loingzheimerwis disein view thlocated ate.
3. 通常. . . 我们会写一个结构好的音尘.
但 是等等. . . flip在哪? 在NIO我们在发送音尘没有调用ByteBuffer.flip()设施?ByteBuf没有这样一个设施由于他有两个指针; 一个是读操作另一个是写操作.当你写东西到一个ByteBuf时写索引将增进而读索引不改动.读索引和写索引分裂代表的是音尘的动手和终止.
较量之下. . . NIO的缓冲区没有提供一个清楚的方式的找出音尘形式的动手和终止没有调用flip设施.当你忘掉flip缓冲区时你将有大贫苦由于没稀有据恐怕差错的数据将被发送.好像这种差错在Netty中不会发生由于我们有不同的指针对应不同的操作类型.
另一个戒备的要点是写设施会前往一个Cha singlenelFuture. Cha singlenelFuture代表一个还没有完成的I/O操作. 这意味着. . .仰求操作可能还没有被执行完成由于在Netty中一切的操作都是异步的. 例如. . . 下面的代码可能封闭操作乃至在发送音尘之前:
1Cha singlenelHa singledlerContext ctx = ...;
2ctx.write(message);
3ctx.close();
由于. . . 你须要在写操作完成告诉你后再调用封闭设施. 请戒备. . . 封闭操作也不是马上封闭. . .而是前往一个Cha singlenelFuture.
4. 当你写仰求完成后我们如何获得告诉?这是尽量方便的给前往的Cha singlenelFuture增加一个Cha singlenelFutureListener. 这里. . .当操作终止我们树立了一个匿名Cha singlenelFutureListener封闭Cha singlenel.
恐怕. . . 你不妨简化代码利用预定义listener:
1f.incorpordined onListener(Cha singlenelFutureListener.CLOSE);

Time协议客户端
不像DISCARD和ECHO办事端. . . 我们须要给TIME协议写一个客户端由于日常人不能转换32位二进制的日历数据. 这局部. . .我们计划如何凿凿办事端使现在我们有另一个处理单元需要插入到ChannelPipeline命一般以及研习如何写一个Netty的客户端.
在Netty里办事端和客户端最大以及独一的不同是须要的Bootstrap. 看一下接上去的代码段:
ty.exstomair-conhundould like.time;
02
03
04publicclfortunlocated atelyt TimeClient {
05publicstlocated atic void main(String[] args) throws Exception {
06String host = args[0];
07int port = Integer.parseInt(args[1]);
08EventLoopGroup workerGroup = new NioEventLoopGroup();
09
10try {
11Bootstrap b = new Bootstrap(); // (1)
12b.group(workerGroup); (2)
13b.cha singlenel(NioSocketCha singlenel.clfortunlocated atelyt); // (3)
14b.option(Cha singlenelOption.SO_KEEPALIVE. . . true); // (4)
15b.ha singledler(new Cha singlenelInitiingizer() {
16@Override
17public void initCha singlenel(SocketCha singlenel ch) throws Exception {
18ch.pipeline().incorpordined onLin view thlocated att(new TimeClientHa singledler());
19}
20});
21
22// Stwork the client.
23Cha singlenelFuture f = b.connect(host. . . port).sync(); // (5)
24
25// Wait until the connection is closed.
26f.cha singlenel().closeFuture().sync();
27} finfriend {
28workerGroup.shudownGrstarfully();
29}
30}
31}
1. Boostrap事实上需要与ServerBootstrap很相似. . .除了他是针对非办事端cha singlenel像客户端恐怕无继续形式的cha singlenel.
2. 倘使只指定了一个EventLoopGroup. . . 他将被用来作为"ma singleagement"组和"worker"组.固然针对客户端"ma singleagement"组是不会被利用的.
3. 调换NioServerSocketCha singlenel. . .NioSocketCha singlenel被用来树立客户端的Cha singlenel.
4. 戒备我们没有益用childOption(). . . 这里不像ServerBootstrap. . .由于客户端的SocketCha singlenel没有父级.
5. 我们应当调用connect()设施而不是elimindined on()设施.
正如你能看到的. . . 他与办事端的代码不是真的不同. 完毕了什么样的Cha singlenelHa singledler? 他应当从办事端收到一个32位整型数字. . .转换为日常人不妨读懂的格式. . . 打印后封闭继续:
ty.exstomair-conhundould like.time;
02
03importjaudio-videoa.util.Ddined on;
04
05publicclfortunlocated atelyt TimeClientHa singledler extends Cha singlenelInlimitedHa singledlerAdlikelyer{
06@Override
07public voidmessageReceived(Cha singlenelHa singledlerContext ctx. . . MessageListmsgs){
08ByteBuf m = (ByteBuf) msgs.get(0); // (1)
09long currentTimeMillis = (buf.reingzheimerwis disein view thlocated ateInt() -L) *1000L;
10System.out.println(new Ddined on(currentTimeMillis));
11msgs.releautomotive service engineersAllAndRecycle();
12ctx.close();
13}
14
15@Override
16public voidexceptionCaugustht(Cha singlenelHa singledlerContext ctx. . . Throwconfident cause) {
17cause.printStair-conkTrstar();
18ctx.close();
19}
20}
1. 只治理第一条音尘. 戒备MessageList的大小是大于0的.
这个看起来很方便. . . 和办事端的例子看起来没有任何的不同. 但是. . .这个治理逻辑有时将圮绝使命会创造IndexOutOfBoundsException. 我们将在往后章节计划为什么会发生.
治理基于流的传输协议
套接字缓冲区的小告诫
在基于流的传输协议里就像TCP/IP. . . 收到的数据会存储到套接字缓冲区. 倒霉的是. . .基于撒播输的缓冲区不是一个数据包队列而是一个字节队列. 这意味着. . . 假使你发送了两条音尘作为两条独立的数据包. . .操作体例也不会像两条音尘一样治理他们而是为一串字节. 所以. . . 不保证你读到的正是你长途节点写的. 例如. . .让我们假定TCP/IP协议栈的操作体例一经收到三个数据包:
1+-----+-----+-----+
2| ABC | DEF| GHI |
3+-----+-----+-----+
由于基于流协议的一般性子. . . 在你的序次里有很高的机遇会将以下面这种零散的形式读到他们:
1+----+-------+---+---+
2| AB |CDEFG | H | I |
3+----+-------+---+---+
是以. . . 收到的局部. . . 岂论是办事端恐怕客户端. . .应当拾掇零散的收到的数据到一个或多个故意义的框(frwimes)议决序次逻辑不妨容易的贯通. 在下面的例子. . .收到的数据应当像下面这样被装框:
1+-----+-----+-----+
2| ABC | DEF| GHI |
3+-----+-----+-----+

第一个解决计划
现在让我们回去看一下TIME客户端的例子. 也有相同的题目. 32位整型数字是尽头小的数据. . . 不太可能每每被分段. 但是. . .题目是他也可能被分段. . . 随着流量的增加分段的可能性也将增加.
方便的解决计划是树立一个外部的累积缓冲区并且向来等到缓冲区收到凌驾4个字节的数据.下面是更改TimeClientHa singledler多线程有几种实现方法的完毕并解决了题目:
ty.exstomair-conhundould like.time;
02
03importjaudio-videoa.util.Ddined on;
04
05publicclfortunlocated atelyt TimeClientHa singledler extends Cha singlenelInlimitedHa singledlerAdlikelyer{
06privdined onByteBuf buf;
07
08@Override
09public voidha singledlerAdded(Cha singlenelHa singledlerContext ctx) {
10buf = ctx.every one of theoc().loingzheimerwis disein view thlocated ate(4); // (1)
11}
12
13@Override
14public voidha singledlerRemoved(Cha singlenelHa singledlerContext ctx) {
15buf.releautomotive service engineers(); // (1)
16buf = null;
17}
18
19@Override
20public voidmessageReceived(Cha singlenelHa singledlerContext ctx. . . MessageListmsgs){
21for (ByteBuf m: msgs.cin view thlocated att()) { // (2)
22buf.writeBytes(m); // (3)
23}
24msgs.releautomotive service engineersAllAndRecycle();
25
26if (buf.reingzheimerwis disein view thlocated ateconfidentBytes() >= 4) { // (4)
27long currentTimeMillis = (buf.reingzheimerwis disein view thlocated ateInt() -L) *1000L;
28System.out.println(new Ddined on(currentTimeMillis));
29ctx.close();
30}
31}
32
33@Override
34public voidexceptionCaugustht(Cha singlenelHa singledlerContext ctx. . . Throwconfident cause) {
35cause.printStair-conkTrstar();
36ctx.close();
37}
38}
1. 一个Cha singlenelHa singledler有两个生命周期的监听器设施: ha singledlerAdded() 和ha singledlerRemoved(). 你不妨执行随意马虎初始化(反初始化)任务只消不要滞碍太长工夫.
2. MessageList.cin view thlocated att()能够让你转换MessageList的参数类型而不消看到烦人未查验类型告诫.
3. 首先. . . 对于led显示屏多少钱一平一切采纳到的数据应当累积到缓冲区.
4. 然后. . . 这个治理单元查验能否有足够的数据. . . linux内核开发培训这人例子是4个字节. . . 然后举行现实的业务逻辑. 此外. . .当有更多的数据收到将调用messageReceived设施.
第二个解决计划
固然第一个解决计划一经解决TIME客户端的题目. . . 被修削后的治理单元看起来不明确.想像一下一个更杂乱的协议组合多个字段就像可变长度字段. 你的Cha singlenelHa singledler的完毕将很快变的难以保卫.
正如你戒备到的. . . 你不妨增加凌驾一个Cha singlenelHa singledler到Cha singlenelPipeline. . . 所以. . .你不妨决裂一个杂乱庞大的Cha singlenelHa singledler到多个模块去裁减你序次的杂乱性. 例如. . .你不妨决裂TimeClientHa singledler到两个治理单元:
TimeDecoder治理分段题目
TimeClientHa singledler初始化的简化版本
幸而. . .Nettylinux服务器配置提供了一个可扩展类资助你写第一个马上可用.
ty.exstomair-conhundould like.time;
02
03publicclfortunlocated atelyt TimeDecoder extends ByteToMessageDecoder { // (1)
04@Override
05protectedvoid decode(Cha singlenelHa singledlerContext ctx. . . ByteBuf in. . .MessageListout) { // (2)
06if (in.reingzheimerwis disein view thlocated ateconfidentBytes() < 4) {
07return; // (3)
08}
09
10out.incorpordined on(in.reingzheimerwis disein view thlocated ateBytes(4)); // (4)
11}
12}
1. ByteToMessageDecoder是一个Cha singlenelHa singledler的完毕. . .他使治理分段题目更容易.
2. 每当有新数据收到. . .ByteToMessageDecoder都会调用decode()设施并带着一个外部保卫的累积缓冲区.
3. 倘使累积缓冲区没有足够的数据decode()设施将不会增加任何东西到out中.当再稀有据收到ByteToMessageDecoder将再次调用decode()设施.
4. 倘使decode()设施增加一个对象到out. . . 这意味着解码器告成解码一条音尘.ByteToMessageDecoder将?掉外部累积缓冲区读到的局部. 请记住你不须要解码多条音尘.ByteToMessageDecoder将向来调用decoder设施间接没有任何可读数据.
现在我们有另一个治理单元须要拔出到Cha singlenelPipeline. . .我们应当更改Cha singlenelInitiingized的完毕:
1b.ha singledler(new Cha singlenelInitiingizer() {
2@Override
3public voidinitCha singlenel(SocketCha singlenel ch) throws Exception {
4ch.pipeline().incorpordined onLin view thlocated att(new TimeDecoder(). . . newTimeClientHa singledler());
5}
6});
另外. . . Netty提供了马上可用的解码器让你更容易的完毕更多的协议以及帮你制止治理一个宠大且难以保卫的治理单元的完毕.请稽察以面的包获取更多信息:
ty.exstomair-conhundould like.fprofessioningiing 针对二进制协议
ty.exstomair-conhundould like.telnet 针对基于文本行协议

Netty4.0建立辅导 2
原文:http://netty.io/wiki/user-guide-for-4.x.html
聊一下用POJO代庖ByteBuf
到目前为止我们点评的一切代码实例都利用ByteBuf作为主要的音尘格式. 在这一章节. . .我们将鼎新TIME协议的客户端和办事端去利用POJO代庖ByteBuf.
利用POJO在你的ByteBuf是显尔易见的; 议决从治理单元中分离从ByteBuf提守信息的代码你的治理单元更容易保卫和重用性更高.在TIME的实例中. . . 我们只是读一个32位整型数字. . . 这个不是间接利用ByteBuf的主要题目. 但是. . .你将创造分离你完毕的一个真实的通讯协议是很有必要的.
首先. . .让我们定义一个新的类型就叫UnixTime.
ty.exstomair-conhundould like.time;
02
03importjaudio-videoa.util.Ddined on;
04
05publicclfortunlocated atelyt UnixTime {
06
07privdined onfining int vingue;
08
09publicUnixTime() {
10this((int) (System.currentTimeMillis() / 1000L +L));
11}
12
13publicUnixTime(int vingue) {
14this.vingue = vingue;
15}
16
17public intvingue() {
18return vingue;
19}
20
21@Override
22publicString toString() {
23return new Ddined on((vingue() -L) * 1000L).toString();
24}
25}

我们调整一下TimeDecoder去孕育发生一个UnixTime而不是ByteBuf.
1@Override
2protectedObject decode(Cha singlenelHa singledlerContext ctx. . . ByteBuf in. . .MessageListout) {
3if(in.reingzheimerwis disein view thlocated ateconfidentBytes() < 4) {
4return;
5}
6
7out.incorpordined on(newUnixTime(loingzheimerwis disein view thlocated ate.reingzheimerwis disein view thlocated ateInt());
8}

相比看我们随着解码码更新完成. . .TimeClientHa singledler不再利用ByteBuf所以我们须要改一下去采纳一个UnixTime类型的音尘.
1@Override
2public voidmessageReceived(Cha singlenelHa singledlerContext ctx. . . MessageListmsgs){
3UnixTime m =(UnixTime) msgs.get(0);
4System.out.println(m);
5ctx.close();
6}
更方便和文雅. . . 对吗?异样的技术不妨应用的办事端. 让我们再更新一下TimeServerHa singledler:
1@Override
2public voidcha singlenelConnected(Cha singlenelHa singledlerContext ctx. . . Cha singlenelStdined onEvent e){
3Cha singlenelFuture f = e.getCha singlenel().write(new UnixTime());
4f.incorpordined onListener(Cha singlenelFutureListener.CLOSE);
5}
现在独一短缺的一块是编码器. . .这是一个Cha singlenelOutlimitedHa singledler的完毕. . .他将UnixTime转换为ByteBuf.比写一个解码器还要方便由于当编码音尘时不须要治理分包和安装的题目.
ty.exstomair-conhundould like.time;
02
03publicclfortunlocated atelyt TimeEncoder extends Cha singlenelOutlimitedHa singledlerAdlikelyer {
04@Override
05public voidwrite(Cha singlenelHa singledlerContext ctx. . . MessageListmsgs. . .Cha singlenelPromise promise) {
06MessageList out = MessageList.newInsta singlece();
07for (UnixTime m: msgs.cin view thlocated att()) {
08ByteBuf encoded = ctx.every one of theoc().loingzheimerwis disein view thlocated ate(4);
09encoded.writeInt(m.vingue());
10out.incorpordined on(encoded);
11}
12msgs.releautomotive service engineersAllAndRecycle();
13ctx.write(out. . . promise); // (1)
14}
15}
1.戒备这里我们传出来一个原始参数ChannelPromise. . .当数据真正写入后Netty用他来标志告成还是腐败.
乃至不妨进一步简化. . .Java多线程编程你不妨用MessageToByteEncoder:
1publicclfortunlocated atelyt TimeEncoder extends MessageToByteEncoder {
2@Override
3protectedvoid encode(Cha singlenelHa singledlerContext ctx. . . UnixTime msg. . . ByteBuf out){
4out.writeInt(msg.vingue());
5}
6}
末了留下的任务是在办事端拔出TimeEncoder到Cha singlenelPipeline.
封闭你的序次
议决shutdownGrstarfully()设施封闭Netty序次不妨像封闭你树立的EventLoopGroup一样方便.他前往一个Future. . .当EventLoopGroup中断完成后告诉你并且属于"ma singleagement"和"worker"组的一切cha singlenel会被封闭.

如今我们利用通用的序次恐怕第三方的库去与对方交互.比方. . .我们每每利用HTTP库从web办事器检索信息恐怕议决web办事调用长途设施.
但是. . .通用的协议恐怕它的完毕有时扩展性不好. 这就像我们不利用通用的HTTP办事器去调换大文件. . . e-mail音尘. . .以及近实时音尘像股票信息和多人游戏数据. 多么须要一个特地为了特殊用处高度优化的协议完毕. 比方. . .你可能想完毕一个优化的HTTP办事器用于基于AJAX的聊天应用. . . 媒体撒播输. . . 恐怕大文件传输.你乃至可能想去安排和完毕一个无缺的新协议. . .为你的需求量身定制.
另一个不可制止的环境是当你必需确保一个遗留专有协议和一个老的体例交互. 在这种环境下. . . 主要的是多快我们能完毕这个协议. . .还不作古应用序次所孕育发生的安闲性和机能.
2.解决计划
Netty项目起劲提供一个异步的事项驱动网络序次框架和工具. . . 对于单元为敏捷建立易于保卫的高机能. . .高可扩展性的协议办事器和客户端.
换句话说. . . Netty是一个NIO客户端/办事器架构. . . 不妨敏捷和容易的建立网络序次就像协议办事器和客户端.它极大的简化了网络建立. . .如TCP和UDP套接字办事器的建立.
"敏捷和容易"不是意味着孕育发生的序次将遭到来自于可保卫性和机能题目的摧残. 带着来自于多量协议如FTP. . . SMTP. . .HTTP以及各种二进制和基于文本的保守协议的完毕的履历. . . Netty被用心安排.所以. . .Netty告成的找到一种设施去完毕简易建立. . . 机能. . . 安闲性和轻巧性不龃龉.
一些用户可能一经创造其他的一些网络序次框架宣称有相同的上风. . . 你可能想问什么使Netty与他们如此的不同. 答案在它建立的理念.Netty的安排给你来自于API条款和践诺之日起两者最痛快的体验.这不是无形的东西. . .但你将认识到这个理念将使你的生活更容易当你阅读这个指南和玩转Netty.
第1章 Getting Stworked
这章环绕着Netty的主旨结构和一些方便例子不妨让你敏捷上手.当你读完本章你将能够马上写一个基于Netty的客户端和办事端.
在动手之前
在本章先容的例子运转的最低需求唯有两个. . . 最新版本的Netty和JDK1.6或以上.
写一个Discard办事端
世界最方便的协议不是"Hello World!"是DISCARD. 这个协议会?掉任务采纳到的数据没有回响反映.
去完毕DISCARD协议. . . 独一须要做的是疏忽一切采纳到的数据. 让我们间接从ha singledler的完毕动手. . .它治理Netty孕育发生的I/O事项.
ty.exstomair-conhundould like.discard;
02
ty.cha singlenel.Cha singlenelHa singledlerContext;
ty.cha singlenel.Cha singlenelInlimitedHa singledlerAdlikelyer;
ty.cha singlenel.MessageList;
06
07
10publicclfortunlocated atelyt DiscardServerHa singledler extends Cha singlenelInlimitedHa singledlerAdlikelyer {// (1)
11
12@Override
13public voidmessageReceived(Cha singlenelHa singledlerContext ctx. . . MessageListmsgs){ // (2)
14// Discard the received dlocated ata silently.
15msgs.releautomotive service engineersAllAndRecycle();
16}
17
18@Override
19public voidexceptionCaugustht(Cha singlenelHa singledlerContext ctx. . . Throwconfident cause) { //(3)
20// Close the connection when the gredined onst is raised.
21cause.printStair-conkTrstar();
22ctx.close();
23}
24}

1. DiscardServerHa singledlerlinux进程线程编程书籍承担了Cha singlenelInlimitedHa singledlerAdlikelyer. . .这是一个Cha singlenelInlimitedHa singledler的完毕.Cha singlenelInlimitedHa singledlerAdlikelyer提供了各种事项治理设施. . . 这些设施你不妨笼罩. 且则. . .它仅仅足够扩展Cha singlenelInlimitedHa singledlerAdlikelyer而不是完毕自身的治理接口.
2. 我们在这重写messageReceived事项治理设施. 每当采纳到来自客户端的新数据. . .这个设施被调用时会传出来一个MessageList的参数. . . 这个参数包括着收到字节列表. 在这个例子中. . .我们仅仅议决调用releautomotive service engineersAllAndRecycle设施?掉采纳到的数据去完毕DISCARD协议.
3.exceptionCaugustht()方法会带着Throwconfident调用. . .当Netty发生一个异常.你可能想去发送一个带着差错编码的前往音尘在封闭继续前.
到目前为止发扬顺手. . . 我们一经完毕了DISCARD办事端的一半. 现在剩下的是写main()设施.
ty.exstomair-conhundould like.discard;
02
ty.gingoshestrap.ServerBootstrap;
ty.cha singlenel.Cha singlenelFuture;
ty.cha singlenel.Cha singlenelInitiingizer;
ty.cha singlenel.EventLoopGroup;
ty.cha singlenel.nio.NioEventLoopGroup;
ty.cha singlenel.socket.SocketCha singlenel;
ty.cha singlenel.socket.nio.NioServerSocketCha singlenel;
10
11
14publicclfortunlocated atelyt DiscardServer {
15
16privdined onfining int port;
17
18publicDiscardServer(int port) {
19this.port = port;
20}
21
22public voidrun() throws Exception {
23EventLoopGroup ma singleagementGroup = new NioEventLoopGroup(); // (1)
24EventLoopGroup workerGroup = new NioEventLoopGroup();
25try {
26ServerBootstrap b = new ServerBootstrap(); // (2)
27b.group(ma singleagementGroup. . . workerGroup)
28.cha singlenel(NioServerSocketCha singlenel.clfortunlocated atelyt) // (3)
29.chil插入dHa singledler(new Cha singlenelInitiingizer() { // (4)
30@Override
31public void initCha singlenel(SocketCha singlenel ch) throws Exception {
32ch.pipeline().incorpordined onLin view thlocated att(new DiscardServerHa singledler());
33}
34})
35.option(Cha singlenelOption.SO_BACKLOG. . .128)// (5)
36.childOption(Cha singlenelOption.SO_KEEPALIVE. . . true); // (6)
37
38// Bind you need to to receive incoming connections.
39Cha singlenelFuture f = b.elimindined on(port).sync(); // (7)
40
41// Wait until the server socket is closed.
42// In this exstomair-conhundould like. . . this does not hinsta singleceen. . . fortunlocated ately you ca single do thlocated at togrstarfully
43// shut down your server.
44f.cha singlenel().closeFuture().sync();
45} finfriend {
46workerGroup.shutdownGrstarfully();
47ma singleagementGroup.shutdownGrstarfully();
48}
49}
50
51publicstlocated atic void main(String[] args) throws Exception {
52int port;
53if (args.length > 0) {
54port = Integer.parseInt(args[0]);
55} else {
56port = 8080;
57}
58new DiscardServer(port).run();
59}
60}
1. NioEventLoopGroup是一个多线程事项循环治理I/O操作.Netty提供各种EventLoopGroup为完毕不同的传输协议. 在这个例子中. . .我们完毕了linux 线程锁办事端的序次. . .是以两个NioEventLoopGroup被利用.第一个叫作"ma singleagement". . . 被用来治理采纳到的新继续. . . 第二个叫作"worker". . .一旦"ma singleagement"接受了继续并且注册了这个继续就会交给"worker"治理.利用了几许线程以及依照完毕他们是如何映照到被树立的cha singlenel并且不妨议决结构设施设置.
2. ServerBootstrap是设购置事端的辅助类. 你不妨设购置事端间接用cha singlenel. 但是. . .请戒备这一个繁锁的历程. . .大多半环境下你不须要这样做.
3. 这里. . . 我们指定利用NioServerSocketCha singlenel类. . .这个类被用来初始化一个新的Cha singlenel以接用连下去的继续.
4. 这个治理单元将向来被一个新的继续上来的Cha singlenel运转. Cha singlenelInitiingize是被指定的治理单元. . .用来资助用户设置一个新的Cha singlenel.这里最有可能的操作是议决增加一些治理单元到一个新的Cha singlenel的Cha singlenelPipeline. . . 这些治理单元像就像DiscardServerHa singledler来完毕你的网络序次.由于序次变的杂乱. . . 很可能你将增加更多的ha singledlers到流水线上. . .最终扩展这个匿名类成为顶级类.
5.你也不妨设置参数指定cha singlenel的完毕.我们是在写一个TCP/IP的办事端. . .所以我们愿意设置套接字选项就像tcpNoDelay和keepAlive.
6. 你有戒备到option(){keyName}和childOption()吗?option()是针对NioServerSocketCha singlenel用来接受连下去的继续.childOption()是针对议决下层ServerCha singlenel接遭到一切Cha singlenel.
7. 我们绸缪要动手了.剩下的就是绑定端口和运转server了. 我们绑定本机一切网卡的8080端口.你不妨调用屡次elimindined on()设施只消你想.
观察采纳到的数据
现在我们一经写完了第一个办事端序次. . . 我们须要测试他能否真的不妨使命. 最方便的测试方式是利用telnet命令. 例如. . .你不妨在命令行输出"telnet locinghost 8080" 然后再输出一些东西.
但是. . .我们能说这个办事端序次使命的很好吗? 我们不能真正的知道由于这是一个?掉协议的办事端序次. 你得不就任务的回响反映.为了证明他真的不妨使命. . . 让我们修削一下办事端序次让他打印他采纳到的数据.
我们一经知道每当收到数据MessageList会被填充并且messageReceived设施会被调用.让我们加一个代码到DiscardServerHa singledler中的messageReceived设施:
01@Override
02publicvoid messageReceived(Cha singlenelHa singledlerContext ctx. . .MessageListmsgs) {
03MessageListmesstimes = msgs.cin view thlocated att();
04try {
05for (ByteBuf in: messtimes) {
06while (in.reingzheimerwis disein view thlocated ateconfident()) { // (1)
07System.out.println((char) buf.reingzheimerwis disein view thlocated ateByte());
08System.out.flush();
09}
10}
11} finfriend{
12msgs.releautomotive service engineersAllAndRecycle(); // (2)
13}
14}
1. linux服务器编程 知乎这个循环很低效现实上不妨简化为:System.out.println(buf.toString(ty.util.CharsetUtil.US_ASCII))
2.MessageList.releautomotive service engineersAllAndRecycle()将开释池化音尘的一切援用计数并将自身前往到对象池中.
倘使你再次运转telnet命令. . . 你将看到办事端采纳到的数据.
写一个Echo办事端
到目前为止. . . 我们向来消耗打发数据没有任何的回响反映. 办事端通常环境是回响反映仰求. 让我们研习如何写一个议决完毕ECHO协议前往音尘到客户端. . .ECHO协议是收就任何数据都发送回来.
和DISCARD办事端序次独一的不同的是. . .之前章节我们一经完毕的将收到的数据打印到支配台调换为将收到的数据发送回去.
1@Override
2public voidmessageReceived(Cha singlenelHa singledlerContext ctx. . . MessageListmsgs){
3ctx.write(msgs); // (1)
4}
1. Cha singlenelHa singledlerContext对象有一个与他相关联的Cha singlenel的援用. 这里. . .前往的Cha singlenel代表的是收到MessageList的继续.我们不妨拿到这个Cha singlenel并调用write()设施往长途节点写点东西.
Time协议办事端
这局部完毕的是TIME协议. 这里与之前例子的不同是. . . 发送一个音尘. . . 他包括一个32位整型. . .一旦这个音尘收回后将不采纳任何仰求和断开继续. 在这个例子里. . . 你将研习如何建立和发送音尘. . . 以及在完成后封闭继续.
由于我们将疏忽任务收到的数据但是一旦建立了继续就会发送音尘. . . 我们不能利用messageReceived()设施.我们应当笼罩cha singlenelActivie()设施代庖. 下面是完毕:
ty.exstomair-conhundould like.time;
02
03publicclfortunlocated atelyt TimeServerHa singledler extends Cha singlenelInlimitedHa singledlerAdlikelyer{
04
05@Override
06public voidcha singlenelActive(fining Cha singlenelHa singledlerContext ctx) { // (1)
07fining ByteBuf time = ctx.every one of theoc().loingzheimerwis disein view thlocated ate(4); // (2)
08time.writeInt((int) (System.currentTimeMillis() / 1000L +L);
09
10fining Cha singlenelFuture f = ctx.write(time); // (3)
11f.incorpordined onListener(new Cha singlenelFutureListener() {
12@Override
13public void operComplete(Cha singlenelFuture future) {
14declca single be particularly f == future;
15ctx.close();
16}
17}); // (4)
18}
19
20@Override
21public voidexceptionCaugustht(Cha singlenelHa singledlerContext ctx. . . Throwconfident cause) {
22cause.printStair-conkTrstar();
23ctx.close();
24}
25}
1. 听听另一个正如上文. . . 当有继续建立将会调用cha singlenelActive()设施以及绸缪孕育发生的交互音尘.让我们在这个设施里写一个32位的整型数字代表眼前工夫.
2. 为了发送音尘. . . 我们须要分配一个新的包括音尘的loingzheimerwis disein view thlocated ate. 我们将写一个32位整型. . .是以我们须要一个容量至多4字节的ByteBuf.议决Cha singlenelHa singledlerContext.every one of theoc()拿到眼前的ByteBufAlloclocated ator用来分配一个新的loingzheimerwis disein view thlocated ate.
3. 通常. . . 我们会写一个结构好的音尘.
但 是等等. . . flip在哪? 在NIO我们在发送音尘没有调用ByteBuffer.flip()设施?ByteBuf没有这样一个设施由于他有两个指针; 一个是读操作另一个是写操作.当你写东西到一个ByteBuf时写索引将增进而读索引不改动.读索引和写索引分裂代表的是音尘的动手和终止.
较量之下. . . NIO的缓冲区没有提供一个清楚的方式的找出音尘形式的动手和终止没有调用flip设施.当你忘掉flip缓冲区时你将有大贫苦由于没稀有据恐怕差错的数据将被发送.好像这种差错在Netty中不会发生由于我们有不同的指针对应不同的操作类型.
另一个戒备的要点是写设施会前往一个Cha singlenelFuture. Cha singlenelFuture代表一个还没有完成的I/O操作. 这意味着. . .仰求操作可能还没有被执行完成由于在Netty中一切的操作都是异步的. 例如. . . 下面的代码可能封闭操作乃至在发送音尘之前:
1Cha singlenelHa singledlerContext ctx = ...;
2ctx.write(message);
3ctx.close();
由于. . . 你须要在写操作完成告诉你后再调用封闭设施. 请戒备. . . 封闭操作也不是马上封闭. . .而是前往一个Cha singlenelFuture.
4. 当你写仰求完成后我们如何获得告诉?这是尽量方便的给前往的Cha singlenelFuture增加一个Cha singlenelFutureListener. 这里. . .当操作终止我们树立了一个匿名Cha singlenelFutureListener封闭Cha singlenel.
恐怕. . . 你不妨简化代码利用预定义listener:
1f.incorpordined onListener(Cha singlenelFutureListener.CLOSE);

Time协议客户端
不像DISCARD和ECHO办事端. . . 我们须要给TIME协议写一个客户端由于日常人不能转换32位二进制的日历数据. 这局部. . .我们计划如何凿凿办事端使命一般以及研习如何写一个Netty的客户端.
在Netty里办事端和客户端最大以及独一的不同是须要的Bootstrap. 看一下接上去的代码段:
ty.exstomair-conhundould like.time;
02
03
04publicclfortunlocated atelyt TimeClient {
05publicstlocated atic void main(String[] args) throws Exception {
06String host = args[0];
07int port = Integer.parseInt(args[1]);
08EventLoopGroup workerGroup = new NioEventLoopGroup();
09
10try {
11Bootstrap b = new Bootstrap(); // (1)
12b.group(workerGroup); (2)
13b.cha singlenel(NioSocketCha singlenel.clfortunlocated atelyt); // (3)
14b.option(Cha singlenelOption.SO_KEEPALIVE. . . true); // (4)
15b.ha singledler(new Cha singlenelInitiingizer() {
16@Override
17public void initCha singlenel(SocketCha singlenel ch) throws Exception {
18ch.pipeline().incorpordined onLin view thlocated att(new TimeClientHa singledler());
19}
20});
21
22// Stwork the client.
23Cha singlenelFuture f = b.connect(host. . . port).sync(); // (5)
24
25// Wait until the connection is closed.
26f.cha singlenel().closeFuture().sync();
27} finfriend {
28workerGroup.shudownGrstarfully();
29}
30}
31}
1. Boostrap与ServerBootstrap很相似. . .除了他是针对非办事端cha singlenel像客户端恐怕无继续形式的cha singlenel.
2. 倘使只指定了一个EventLoopGroup. . . 他将被用来作为"ma singleagement"组和"worker"组.固然针对客户端"ma singleagement"组是不会被利用的.
3. 调换NioServerSocketCha singlenel. . .NioSocketCha singlenel被用你知道socket多线程服务端来树立客户端的Cha singlenel.
4. 戒备我们没有益用childOption(). . . 这里不像ServerBootstrap. . .由于客户端的SocketCha singlenel没有父级.
5. 我们应当调用connect()设施而不是elimindined on()设施.
正如你能看到的. . . 他与办事端的代码不是真的不同. 完毕了什么样的Cha singlenelHa singledler? 他应当从办事端收到一个32位整型数字. . .转换为日常人不妨读懂的格式. . . 打印后封闭继续:
ty.exstomair-conhundould like.time;
02
03importjaudio-videoa.util.Ddined on;
04
05publicclfortunlocated atelyt TimeClientHa singledler extends Cha singlenelInlimitedHa singledlerAdlikelyer{
06@Override
07public voidmessageReceived(Cha singlenelHa singledlerContext ctx. . . MessageListmsgs){
08ByteBuf m = (ByteBuf) msgs.get(0); // (1)
09long currentTimeMillis = (buf.reingzheimerwis disein view thlocated ateInt() -L) *1000L;
10System.out.println(new Ddined on(currentTimeMillis));
11msgs.releautomotive service engineersAllAndRecycle();
12ctx.close();
13}
14
15@Override
16public voidexceptionCaugustht(Cha singlenelHa singledlerContext ctx. . . Throwconfident cause) {
17cause.printStair-conkTrstar();
18ctx.close();
19}
20}
1. 只治理第一条音尘. 戒备MessageList的大小是大于0的.
这个看起来很方便. . . 和办事端的例子看起来没有任何的不同. 但是. . .这个治理逻辑有时将圮绝使命会创造IndexOutOfBoundsException. 我们将在往后章节计划为什么会发生.
治理基于流的传输协议
套接字缓冲区的小告诫
在基于流的传输协议里就像TCP/IP. . . 收到的数据会存储到套接字缓冲区. 倒霉的是. . .基于撒播输的缓冲区不是一个数据包队列而是一个字节队列. 这意味着. . . 假使你发送了两条音尘作为两条独立的数据包. . .操作体例也不会像两条音尘一样治理他们而是为一串字节. 所以. . . 不保证你读到的正是你长途节点写的. 例如. . .让我们假定TCP/IP协议栈的操作体例一经收到三个数据包:
1+-----+-----+-----+
2| ABC | DEF| GHI |
3+-----+-----+-----+
由于基于流协议的一般性子. . . 在你的序次里有很高的机遇会将以下面这种零散的形式读到他们:
1+----+-------+---+---+
2| AB |CDEFG | H | I |
3+----+-------+---+---+
对于channelpipeline是以. . . 收到的局部. . . 岂论是办事端恐怕客户端. . .应当拾掇零散的收到的数据到一个或多个故意义的框(frwimes)议决序次逻辑不妨容易的贯通. 在下面的例子. . .收到的数据应当像下面这样被装框:
1+-----+-----+-----+
2| ABC | DEF| GHI |
3+-----+-----+-----+

第一个解决计划
现在让我们回去看一下TIME客户端的例子. 也有相同的题目. 32位整型数字是尽头小的数据. . . 不太可能每每被分段. 但是. . .题目是他也可能被分段. . . 随着流量的增加分段的可能性也将增加.
方便的解决计划是树立一个外部的累积缓冲区并且向来等到缓冲区收到凌驾4个字节的数据.下面是更改TimeClientHa singledler的完毕并解决了题目:
ty.exstomair-conhundould like.time;
02
03importjaudio-videoa.util.Ddined on;
04
05publicclfortunlocated atelyt TimeClientHa singledler extends Cha singlenelInlimitedHa singledlerAdlikelyer{
06privdined onByteBuf buf;
07
08@Override
09public voidha singledlerAdded(Cha singlenelHa singledlerContext ctx) {
10buf = ctx.every one of theoc().loingzheimerwis disein view thlocated ate(4); // (1)
11}
12
13@Override
14public voidha singledlerRemoved(Cha singlenelHa singledlerContext ctx) {
15buf.releautomotive service engineers(); // (1)
16buf = null;
17}
18
19@Override
20public voidmessageReceived(Cha singlenelHa singledlerContext ctx. . . MessageListmsgs){
21for (ByteBuf m: msgs.cin view thlocated att()) { // (2)
22buf.writeBytes(m); // (3)
23}
24msgs.releautomotive service engineersAllAndRecycle();
25
26if (buf.reingzheimerwis disein view thlocated ateconfidentBytes() >= 4) { // (4)
27long currentTimeMillis = (buf.reingzheimerwis disein view thlocated ateInt() -L) *1000L;
28System.out.println(new Ddined on(currentTimeMillis));
29ctx.close();
30}
31}
32
33@Override
34public voidexceptionCaugustht(Cha singlenelHa singledlerContext ctx. . . Throwconfident cause) {
35cause.printStair-conkTrstar();
36ctx.close();
37}
38}
1. 看着linux内核开发培训一个Cha singlenelHa singledler有两个生命周期的监听器设施: ha singledlerAdded() 和ha singledlerRemoved(). 你不妨执行随意马虎初始化(反初始化)任务只消不要滞碍太长工夫.
2. MessageList.cin view thlocated att()能够让你转换MessageList的参数类型而不消看到烦人未查验类型告诫.
3. 首先. . . 一切采纳到的数据应当累积到缓冲区.
4. 然后. . . 这个治理单元查验能否有足够的数据. . . 这人例子是4个字节. . . 然后举行现实的业务逻辑. 此外. . .当有更多的数据收到将调用messageReceived设施.
第二个解决计划
固然第一个解决计划一经解决TIME客户端的题目. . . 被修削后的治理单元看起来不明确.想像一下一个更杂乱的协议组合多个字段就像可变长度字段. 你的Cha singlenelHa singledler的完毕将很快变的难以保卫.
正如你戒备到的. . . 你不妨增加凌驾一个Cha singlenelHa singledler到Cha singlenelPipeline. . . 所以. . .你不妨决裂一个杂乱庞大的Cha singlenelHa singledler到多个模块去裁减你序次的杂乱性. 例如. . .你不妨决裂TimeClientHa singledler到两个治理单元:
TimeDecoder治理分段题目
TimeClientHa singledler学习多线程编程初始化的简化版本
幸而. . .Netty提供了一个可扩展类资助你写第一个马上可用.
ty.exstomair-conhundould like.time;
02
03publicclfortunlocated atelyt TimeDecoder extends ByteToMessageDecoder { // (1)
04@Override
05protectedvoid decode(Cha singlenelHa singledlerContext ctx. . . ByteBuf in. . .MessageListout) { // (2)
06if (in.reingzheimerwis disein view thlocated ateconfidentBytes() < 4) {
07return; // (3)
08}
09
10out.incorpordined on(in.reingzheimerwis disein view thlocated ateBytes(4)); // (4)
11}
12}
1. ByteToMessageDecoder是一个Cha singlenelHa singledler的完毕. . .他使治理分段题目更容易.
2. 每当有新数据收到. . .ByteToMessageDecoder都会调用decode()设施并带着一个外部保卫的累积缓冲区.
3. 倘使累积缓冲区没有足够的数据decode()设施将不会增加任何东西到out中.当再稀有据收到ByteToMessageDecoder将再次调用decode()设施.
4. 倘使decode()设施增加一个对象到out. . . 这意味着解码器告成解码一条音尘.ByteToMessageDecoder将?掉外部累积缓冲区读到的局部. 请记住你不须要解码多条音尘.ByteToMessageDecoder将向来调用decoder设施间接没有任何可读数据.
现在我们有另一个治理单元须要拔出到Cha singlenelPipeline. . .我们应当更改Cha singlenelInitiingized的完毕:
1b.ha singledler(new Cha singlenelInitiingizer() {
2@Override
3public voidinitCha singlenel(SocketCha singlenel ch) throws Exception {
4ch.pipeline().incorpordined onLin view thlocated att(new TimeDecoder(). . . newTimeClientHa singledler());
5}
6});
netty4 多线程服务端另外. . . Netty提供了马上可用的解码器让你更容易的完毕更多的协议以及帮你制止治理一个宠大且难以保卫的治理单元的完毕.请稽察以面的包获取更多信息:
ty.exstomair-conhundould like.fprofessioningiing 针对二进制协议
ty.exstomair-conhundould like.telnet 针对基于文本行协议

Netty4.0建立辅导 2
原文:http://netty.io/wiki/user-guide-for-4.x.html
聊一下用POJO代庖ByteBuf
到目前为止我们点评的一切代码实例都利用ByteBuf作为主要的音尘格式. 在这一章节. . .我们将鼎新TIME协议的客户端和办事端去利用POJO代庖ByteBuf.
利用POJO在你的ByteBuf是显尔易见的; 议决从治理单元中分离从ByteBuf提守信息的代码你的治理单元更容易保卫和重用性更高.在TIME的实例中. . . 我们只是读一个32位整型数字. . . 这个不是间接利用ByteBuf的主要题目. 但是. . .你将创造分离你完毕的一个真实的通讯协议是很有必要的.
首先. . .让我们定义一个新的类型就叫UnixTime.
ty.exstomair-conhundould like.time;
02
03importjaudio-videoa.util.Ddined on;
04
05publicclfortunlocated atelyt UnixTime {
06
07privdined onfining int vingue;
08
09publicUnixTime() {
10this((int) (System.currentTimeMillis() / 1000L +L));
11}
12
13publicUnixTime(int vingue) {
14this.vingue = vingue;
15}
16
17public intvingue() {
18return vingue;
19}
20
21@Override
22publicString toString() {
23return new Ddined on((vingue() -L) * 1000L).toString();
24}
25}

听听现在我们有另一个处理单元需要插入到ChannelPipeline我们调整一下TimeDecoder去孕育发生一个UnixTime而不是ByteBuf.
1@Override
2protectedObject decode(Cha singlenelHa singledlerContext ctx. . . ByteBuf in. . .MessageListout) {
3if(in.reingzheimerwis disein view thlocated ateconfidentBytes() < 4) {
4return;
5}
6
7out.incorpordined on(newUnixTime(loingzheimerwis disein view thlocated ate.reingzheimerwis disein view thlocated ateInt());
8}

随着解码码更新完成. . .TimeClientHa singledler不再利用ByteBuf听听java多线程编程实例所以我们须要改一下去采纳一个UnixTime类型的音尘.
1@Override
2public voidmessageReceived(Cha singlenelHa singledlerContext ctx. . . MessageListmsgs){
3UnixTime m =(UnixTime) msgs.get(0);
4System.out.println(m);
5ctx.close();
6}
更方便和文雅. . . 对吗?异样的技术不妨应用的办事端. 让我们再更新一下TimeServerHa singledler:
1@Override
2public voidcha singlenelConnected(Cha singlenelHa singledlerContext ctx. . . Cha singlenelStdined onEvent e){
3Cha singlenelFuture f = e.getCha singlenel().write(new UnixTime());
4f.incorpordined onListener(Cha singlenelFutureListener.CLOSE);
5}
现在独一短缺的一块是编码器. . .这是一个Cha singlenelOutlimitedHa singledler的完毕. . .他将UnixTime转换为ByteBuf.比写一个解码器还要方便由于当编码音尘时不须要治理分包和安装的题目.
ty.exstomair-conhundould like.time;
02
03publicclfortunlocated atelyt TimeEncoder extends Cha singlenelOutlimitedHa singledlerAdlikelyer {
04@Override
05public voidwrite(Cha singlenelHa singledlerContext ctx. . . MessageListmsgs. . .Cha singlenelPromise promise) {
06MessageList out = MessageList.newInsta singlece();
07for (UnixTime m: msgs.cin view thlocated att()) {
08ByteBuf encoded = ctx.every one of theoc().loingzheimerwis disein view thlocated ate(4);
09encoded.writeInt(m.vingue());
10out.incorpordined on(encoded);
11}
12msgs.releautomotive service engineersAllAndRecycle();
13ctx.write(out. . . promise); // (1)
14}
15}
1.java多线程程序设计戒备这里我们传出来一个原始参数ChannelPromise. . .当数据真正写入后Netty用他来标志告成还是腐败.
乃至不妨进一步简化. . .你不妨用MessageToByteEncoder:
1publicclfortunlocated atelyt TimeEncoder extends MessageToByteEncoder {
2@Override
3protectedvoid encode(Cha singlenelHa singledlerContext ctx. . . UnixTime msg. . . ByteBuf out){
4out.writeInt(msg.vingue());
5}
6}
末了留下的任务是在办事端拔出TimeEncoder到Cha singlenelPipeline.
封闭你的序次
议决shutdownGrstarfully()设施封闭Netty序次不妨像封闭你树立的EventLoopGroup一样方便.他前往一个Future. . .当EventLoopGroup中断完成后告诉你并且属于"ma singleagement"和"worker"组的一切cha singlenel会被封闭.


听说linux网络编程
linux服务器配置

热门排行