为什么使用协议解码过滤器 ProtocolCodecFilter ?
1) TCP保证所有的包以正确是顺序传递,但不保证发送方的一次写操作在接收方产生一次读操作。在 MINA 的术语中:没有 ProtocolCodecFilter ,发送方的一次 IoSession.write(Object message) 导致接收方多次 messageReceived(IoSession session, Object message) 事件,多次调用 IoSession.write(Object message) 可以导致单一的 messageReceived 事件。当服务器和客户端在同一台主机(或同一局域网)时,你可能不会遇到这种行为。但你的应用程序可能会遇到。
2) 大多数应用程序需要一种方法来找出当前消息的结束位置和下一个消息的开始位置。
你可以在IoHandler 里实现这些逻辑,但添加一个 ProtocolCodecFilter 可以使你的代码更加清晰和易于维护。它允许你分离协议逻辑和业务逻辑( IoHandler )。
应用程序基本上是接收一串字节,需要转换这些字节到消息(高层对象)。
有三种常用的技术来分割字节流到消息:
1、使用定长消息
2、使用固定长度的头来指示内容体长度
3、使用分隔符。
这里使用分割符(换行)来编写时间服务器的解码器。
时间服务器的请求对象为java.lang.String,对应的协议解码器为:
org.apache.mina.filter.codec.textline.TextLineEncoder和org.apache.mina.filter.codec.textline.TextLineDecoder。
响应对象定义如下:
public class TimeResponse {
private String client; // 客户端发送到字符串
private Date date;
public TimeResponse(String client, Date date) {
this.client = client;
this.date = date;
}
public String getClient() {
return client;
}
public Date getDate() {
return date;
}
}
下面是响应的编码器:
public class TimeResponseEncoder extends ProtocolEncoderAdapter {
@Override
public void encode(IoSession session, Object message,
ProtocolEncoderOutput out) throws Exception {
TimeResponse res = (TimeResponse) message;
IoBuffer buff = IoBuffer.allocate(32);
buff.setAutoExpand(true);
buff.setAutoShrink(true);
CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
buff.putString(res.getClient() + " 您好!服务器时间是:", encoder);
Date date = res.getDate();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd,HH时mm分ss秒");
buff.putString(sdf.format(date), encoder);
buff.put((byte)'\n');
buff.flip();
out.write(buff);
out.flush();
System.err.println("res encode end .... ");
}
}
业务处理器通过IoSession.write()写出的都是响应对象,所以这里可以直接进行强类型转换
TimeResponse res = (TimeResponse) message;
编码后的内容是写到 ProtocolEncoderOutput out,传给下一个过滤器。
然后是响应的解码器:
public class TimeResponseDecoder extends CumulativeProtocolDecoder {
@Override
protected boolean doDecode(IoSession session, IoBuffer in,
ProtocolDecoderOutput out) throws Exception {
CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
int start = in.position();
int end = in.remaining() - 1;
if (end >= 0 && in.get(end) == (byte) '\n') {
String res = in.getString(decoder);
out.write(res);
return true;
} else {
in.position(start);
}
return false;
}
}
解码器继承自CumulativeProtocolDecoder的好处是,当缓存的内容还不够解码为一个响应对象时,可以继续缓存响应内容,只要返回false即可。
有了请求和响应的编解码器后,定义一个解码器工厂:
public class TimeResponseCodecFactory implements ProtocolCodecFactory {
private ProtocolDecoder decoder;
private ProtocolEncoder encoder;
public TimeResponseCodecFactory(boolean server) {
if(server) {
decoder = new TextLineDecoder(Charset.forName("UTF-8"));
encoder = new TimeResponseEncoder();
} else {
decoder = new TimeResponseDecoder();
encoder = new TextLineEncoder(Charset.forName("UTF-8"));
}
}
@Override
public ProtocolDecoder getDecoder(IoSession session) throws Exception {
return decoder;
}
@Override
public ProtocolEncoder getEncoder(IoSession session) throws Exception {
return encoder;
}
}
MINA会调用工厂的 getDecoder 和 getEncoder 方法。
注意:服务器端的解码器是请求解码器,编码器是响应编码器;客户端的解码器是响应解码器,编码器是请求编码器。
修改服务器和客户端的过滤器配置
connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TimeResponseCodecFactory(true/false)));
服务器端的处理器现在可以直接写响应对象了:
public class TimeServerHandler extends IoHandlerAdapter {
private Logger log = LoggerFactory.getLogger(TimeServerHandler.class);
@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
String str = message.toString();
log.info("server receive :" + str);
if("quit".equalsIgnoreCase(str.trim())) {
session.close(true);
return;
}
Date date = new Date();
TimeResponse res = new TimeResponse(str, date);
session.write(res);
log.info("message writter ...");
}
}
而客户端的处理器也可以直接处理响应对象:
public class ClientHandler extends IoHandlerAdapter {
@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
String msg = (String) message;
System.out.println("response :" + msg);
}
}
有了协议解码过滤器,处理器就不需要考虑底层的编解码的问题,只需要处理高层的业务对象,达到了分层的目的。
转自:http://wen866595.iteye.com/blog/1154137
相关推荐
内容概要:本文全面介绍了Scratch编程语言,包括其历史、发展、特点、主要组件以及如何进行基本和进阶编程操作。通过具体示例,展示了如何利用代码块制作动画、游戏和音乐艺术作品,并介绍了物理模拟、网络编程和扩展库等功能。 适合人群:编程初学者、教育工作者、青少年学生及对编程感兴趣的各年龄段用户。 使用场景及目标:①帮助初学者理解编程的基本概念和逻辑;②提高学生的创造力、逻辑思维能力和问题解决能力;③引导用户通过实践掌握Scratch的基本和高级功能,制作个性化作品。 其他说明:除了基础教学,文章还提供了丰富的学习资源和社区支持,帮助用户进一步提升技能。
mmexport1734874094130.jpg
基于simulink的悬架仿真模型,有主动悬架被动悬架天棚控制半主动悬架 [1]基于pid控制的四自由度主被动悬架仿真模型 [2]基于模糊控制的二自由度仿真模型,对比pid控制对比被动控制,的比较说明 [3]基于天棚控制的二自由度悬架仿真 以上模型,说明文档齐全,仿真效果明显
内容概要:本文档是《组合数学答案-网络流传版.pdf》的内容,主要包含了排列组合的基础知识以及一些经典的组合数学题目。这些题目涵盖了从排列数计算、二项式定理的应用到容斥原理的实际应用等方面。通过对这些题目的解析,帮助读者加深对组合数学概念和技巧的理解。 适用人群:适合初学者和有一定基础的学习者。 使用场景及目标:可以在学习组合数学课程时作为练习题参考,也可以在复习考试或准备竞赛时使用,目的是提高解决组合数学问题的能力。 其他说明:文档中的题目覆盖了组合数学的基本知识点,适合逐步深入学习。每个题目都有详细的解答步骤,有助于读者掌握解题思路和方法。
YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;
操作系统实验 Ucore lab5
基于matlab开发的学生成绩管理系统GUI界面,可以实现学生成绩载入,显示,处理及查询。
老版本4.0固件,(.dav固件包),支持7700N-K4,7900N-K4等K51平台,升级后出现异常或变砖可使用此版本。请核对自己的机器信息,确认适用后在下载。
YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;
YOLO算法-杂草检测项目数据集-3970张图像带标签-杂草.zip
E008 库洛米(3页).zip
内容概要:本文详细阐述了基于西门子PLC的晶圆研磨机自动控制系统的设计与实现。该系统结合了传感器技术、电机驱动技术和人机界面技术,实现了晶圆研磨过程的高精度和高效率控制。文中详细介绍了控制系统的硬件选型与设计、软件编程与功能实现,通过实验测试和实际应用案例验证了系统的稳定性和可靠性。 适合人群:具备一定的自动化控制和机械设计基础的工程师、研究人员以及从事半导体制造的技术人员。 使用场景及目标:本研究为半导体制造企业提供了一种有效的自动化解决方案,旨在提高晶圆研磨的质量和生产效率,降低劳动强度和生产成本。系统适用于不同规格晶圆的研磨作业,可以实现高精度、高效率、自动化的晶圆研磨过程。 阅读建议:阅读本文时,重点关注晶圆研磨工艺流程和技术要求,控制系统的硬件和软件设计方法,以及实验测试和结果分析。这将有助于读者理解和掌握该自动控制系统的实现原理和应用价值。
YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;
深圳建筑安装公司“挖掘机安全操作规程”
YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;
大题解题方法等4个文件.zip
保障性安居工程考评内容和评价标准.docx
监督机构检查记录表.docx
该项目适合初学者进行学习,有效的掌握java、swing、mysql等技术的基础知识。资源包含源码、视频和文档 资源下载|如果你正在做毕业设计,需要源码和论文,各类课题都可以,私聊我。 商务合作|如果你是在校大学生,正好你又懂语言编程,或者你可以找来需要做毕设的伙伴,私聊我。。内容来源于网络分享,如有侵权请联系我删除。另外如果没有积分的同学需要下载,请私信我。
218) Leverage - 创意机构与作品集 WordPress 主题 2.2.7.zip