编码器负责将应用程序可以识别的数据结构转化为可传输的数据流,解码器反之。对于应用程序来说,编码器操作出站数据,解码器操作入站数据。
解码器因为是处理入站数据的,所以继承了ChannelInBoundHandler.我们理解的时候可以认为解码器就是一种特殊的Handler,用于处理信息。
ByteToMessageDecoder
// ByteToMessageDecoder
public class ToIntDecoder : ByteToMessageDecoder
{
protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List<object> output)
{
if (input.ReadableBytes >= 4) output.Add(input.ReadInt());
}
}
// 测试代码
[Fact]
public void TestIntDecoder()
{
IByteBuffer buf = Unpooled.Buffer();
for (int i = 0; i < 8; i++)
{
buf.WriteByte(i);
}
// 构建Channel
EmbeddedChannel channel = new EmbeddedChannel(new ToIntDecoder());
// 测试
Assert.True(channel.WriteInbound(buf));
Assert.True(channel.Finish());
// 比如 0 1 2 3
// 3*2^0+2*2^8+1*2^16+0*2^24
Assert.Equal(66051, channel.ReadInbound<int>());
}
ReplayingDecoder
// 不需要判断ReadableBytes的ReplayingDecoder
public class ToIntDecoder2 : ReplayingDecoder<int>
{
public ToIntDecoder2(int initialState) : base(initialState)
{
}
protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List<object> output)
{
output.Add(input.ReadInt());
}
}
MessageToMessageDecoder
public class IntToStringDecoder : MessageToMessageDecoder<int>
{
protected override void Decode(IChannelHandlerContext context, int message, List<object> output)
{
output.Add(message.ToString());
}
}
根据我们之前的知识可以轻易的推导出,Encoder继承了ChannelOutBoundHandler
MessageToByteEncoder
public class ShortToByteEncoder : MessageToByteEncoder<short>
{
protected override void Encode(IChannelHandlerContext context, short message, IByteBuffer output)
{
output.WriteShort(message);
}
}
MessageToMessageEncoder
public class IntToStringEncoder : MessageToMessageEncoder<int>
{
protected override void Encode(IChannelHandlerContext context, int message, List<object> output)
{
output.Add(message.ToString());
}
}
MessageToMessageCodec,它拥有encode和decode两个方法,用于实现来回的转换数据,这种编解码器我们在后面实例的时候再举例说明。
这种编解码器可以把数据的转换,逆转换过程封装,但是同时他的缺点是,不如分开写重用方便。那我们就会想了,既然如此的话,为什么我们不能把一个编码器,一个解码器结合起来,作为一个编解码器呢?这样的话,编码器解码器分别可以重用,结合出来的编解码器也可以方便的使用 CombinedChannelDuplexHandler 就可以实现这样的作用。
// 提供结合的编解码器
public class CombinedCodec : CombinedChannelDuplexHandler<ToIntDecoder, ShortToByteEncoder>
{
}
一、DotNetty介绍 DotNetty是微软的Azure团队,使用C#实现的Netty的版本发布。不但使用了C#和.Net平台的技术特点,并且保留了Netty原来绝大部分的编程接口。让我们在使用时,完全可以依照Netty官方的教程来学习和使用DotNetty应用程序。 那Netty又是什么尼? Netty 是一个提供 asynchronous event-driven (异步事件驱动)的网络应...
DotNetty项目本身的示例很容易运行起来,但是具体到真实的应用场景,还是需要进一步理解DotNetty的通道处理细节,这样才能够在实际项目应用中处理具体的问题。 简单的场景下会有以下几个问题,第一,客户端如何向服务器主动发送消息;第二,服务器如何向指定客户端发送消息;第三,在哪里做报文的拆包和组包。我是带着以上几个问题进行分析的。 以上几个问题,在下面的代码中会有详细的注释,也许不...
一、背景 现在Android上的图片加载框架非常成熟,从最早的老牌图片加载框架UniversalImageLoader,到后来Google推出的Volley,再到后来的新兴军Glide和Picasso,当然还有Facebook的Fresco。每一个都非常稳定,功能也都十分强大。但是它们的使用场景基本都是重合的,也就是说我们基本只需要选择其中一个来进行学习和使用就足够了,每一个框架都尝试去掌握的话则...
闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。 1. 闭包 例子1: 内部的函数inc访问了外层函数a的变量n,所以inc是一个闭包。 例子2: 注意:调用a()返回的是一个函数名,此时c=函数,()才是执行函数 陷阱: 当for循环执行完,i的值已经是4,所以数组里面的每个函数使用的外部函数的i值就是4. 解决这个陷阱要使用匿名函数: 2....
Python基础教程 —— 数据库 1. SQLite入门 2. 将数据导入SQLite 3. 查询SQLite...
###遍历 通过for ... in ...:或者while的语法结构,将字符串、列表、元组、字典等数据结构中的元素循环输出,这种方式就是遍历。 注意python语法的缩进 ####1.1 字符串遍历 示例1: 结果: 示例2: 结果: ####1.2 列表遍历 示例1: 结果: 示例2: 结果: ####1.3 元组遍历 示例1: 结果: 示例2: 结果: ####1.4 字典遍历 <1&...
每一部分都单独注释的,运行时取消注释,将其他部分注释起来就可以。...
模型是关于你数据的单独的,明确的信息源。它包含你储存数据的重要的字段和行为。通常的,每个模型都映射一个单独的数据表。 基本: 每个模型都是继承django.db.models.Model的Python子类 每个模型的属性都表示一个数据库字段。 使用所有这些,Django提供给你一个自动生成数据库访问API;阅读<进行查询>。 1. 简单的例子 这个例子模型定义了一个Person,它有f...
在Golang中不支持重载.不支持类,但是支持自定义方法 方法定义和函数定义很像,它们实际上只有一点不同,就是在函数的前面增加一个额外的叫做接收器的参数名称和类型即可 和任何其他函数一样,需要提供一个接收器参数的名称,后面跟上其类型 为了调用你定义的方法,输入你要调用的方法的值,一个点和要调用的方法名称,跟一对().这里你调用的方法的值被称为方法接收器 调用方法和方法定义的相似之处在于,方法接收器...
https://www.jianshu.com/p/308f3c54abdd 主要是通过注解简化网络访问,实用性的话,没okhttp强 ------------------------------------------------------------------------------------------------------ 本文注目录: Retrofit入门 Retrofit注解详...