Netty框架的学习经历初级篇---helloworld

时间:2023-01-01 22:38:21

每一个程序猿都对helloworld有一段特殊的感情!Netty框架的学习经历初级篇---helloworld

我的学习也是从一段helloworld代码开始的。一开始下载了一个pdf版的netty权威指南,该书是以netty5.0版本讲述的,到netty.io查看,发现已经废弃该版本,还是沿用3.x与4.x,但是想来4到5应该差别不大,然后仿照书中例子开始搞起,结果卡住了,5.0版本的方法在4.x版本中没有,或者已经改名了,改名了还不在同一个包中,一眼黑啊。果断放弃。第二本书 netty教程,这个是3.x版本的,不过也是原作者的探究经历的整理,比较凌乱,而且3.x与4.x版本差别很大,4.x解决了很多问题,而且更加合理。放弃3.x版本。打算进军4.x。果断有大神已经对4.x版本入门级别进行了整理供后来者学习。果断查看啊  来个时空门:http://www.cnblogs.com/zou90512/p/3492287.html

经过一番学习,大概了解了netty的运行方法,成功搭建起了server与client,但是client并没有使用,因为我面对的是硬件设备的client,其内容我是无法做出修改的,所以忽略client。至于详细的代码就不赘述了,自行查看上面的传送门。

这里重点说的是解码器:

上代码

package com.netty.demo2;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.bytes.ByteArrayDecoder;
import io.netty.handler.codec.bytes.ByteArrayEncoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

public class HelloServerInitializer extends ChannelInitializer<SocketChannel>{

@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();

// 以("\n")为结尾分割的 解码器
// pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));

// 字符串解码 和 编码
pipeline.addLast("decoder", new StringDecoder());//解码
pipeline.addLast("encoder", new StringEncoder());//编码
pipeline.addLast("bytesDecoder",new ByteArrayDecoder());
pipeline.addLast("bytesEncoder",new ByteArrayEncoder());
// 自己的逻辑Handler
pipeline.addLast("handler", new HelloServerHandler());
}
}
首先我们看到 
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
这个是基于分隔符\n的解码器,我们可以绕过,其实不需要这个东西,因为我面对的硬件设备是不可能发送的时候带个“\n”的。

后面的StringDecoder,StringEncoder是string 字符串的解码器和编码器,如果你只接收不发送,那么你只需要加载解码器就行,编码器无需加载。再来说一下pipline.addLast(String name, ChannelHandler handler)这个函数,起先我以为

 pipeline.addLast("decoder", new StringDecoder());//解码
中的“decoder”是默认的,只要是解码器都是这个字符串,于是当我加载ByteArrayDecoder和ByteArrayEncoder字节解编码器时也沿用了这两个字符串“decoder”和“encoder”,启动helloserver成功,但当设备连接上时报错,我才意识到,这里的name是不能相同的,于是翻看源码

/**
* Appends a {@link ChannelHandler} at the last position of this pipeline.
*
* <span style="color:#ff0000;">@param name the name of the handler to append
* @param handler the handler to append</span>
*
* @throws IllegalArgumentException
* if there's an entry with the same name already in the pipeline
* @throws NullPointerException
* if the specified handler is {@code null}
*/
ChannelPipeline addLast(String name, ChannelHandler handler);
果真如此,人家写的很明白,只是个名字。

所以该问题解决,如果你需要其他接收发送其他格式的数据,可以自行加载解码编码器。
另外,关于为什么只有在最后的一次addLast中才有或者说才执行消息的收发。原因在于,数据的传输方向,当数据进入服务端时,从上往下一次经过各个解编码器,并同时查找InboundHandler,而inboundhandler中就是处理接收消息的逻辑内容,同理当消息从服务端发送到客户端的时候就反向运行,
查找与之相应的outboundhandler。而且在HelloServerHandler中继承了SimpleChannelInboundHandler,通过覆盖channelRead0与channelActive方法就可以实现消息的收发了。


下一步要解决的就是多客户端问题了!


爱编程,爱学习,爱挑战。

程序猿就是我,我就是程序猿。