Tutorial on ProtocolCodecFilter
Why use a ProtocolCodecFilter?
- TCP guarantess delivery of all packets in the correct order.
But there is no guarantee that one write operation on the sender-side will result in one read event on the receiving side.
TCP保证收发的数据包遵照正确的次序。
但并不保证发送方的写操作会在接收方产生读事件。
In MINA terminology: without a ProtocolCodecFilter one call of IoSession.write(Object message) by the sender can result in multiple messageReceived(IoSession session, Object message) events on the receiver; and multiple calls of IoSession.write(Object message) can lead to a single messageReceived event. You might not encounter this behavior when client and server are running on the same host (or an a local network) but your applications should be able to cope with this.
MINA技术:不用ProtocolCodecFilter的话,发送方的一次写调用IoSession.write(Object message)可能会在接收方产生多个接收事件;多次写调用IoSession.write(Object message)也可能会在接收方导致一个接收事件。当客户端和服务器运行在同一台主机或局域网时,你可能会遇到上述情况,但你的应用程序应该能够处理。
- Most network applications need a way to find out where the current message ends and where the next message starts.
大多数网络应用程序需要识别出当前消息在那儿结束,以及下一个消息在那儿开始。
- You could implement all this logic in your IoHandler, but adding a ProtocolCodecFilter will make your code much cleaner and easier to maintain.
It allows you to separate your protocol logic from your business logic (IoHandler).
你可以将所有的逻辑在IoHandler中实现,但如果加入ProtocolCodecFilter的话,将会使你的代码更清晰,更易维护。
ProtocolCodecFilter允许你将协议逻辑从业务逻辑(IoHandler)中分离出来。
How ?
Your application is basically just receiving a bunch of bytes and you need to convert these bytes into messages (higher level objects).
There are three common techniques for splitting the stream of bytes into messages:
你的应用程序主要就是接收一串字节,你需要将它们转换成消息(高层对象)。
有三种通用技术将字节流分解到消息中:
- use fixed length messages
使用定长消息
- use a fixed length header that indicates the length of the body
使用定长的报文头,在其中某个域指明报文长度
- using a delimiter; for example many text-based protocols append a newline (or CR LF pair) after every message (http://www.faqs.org/rfcs/rfc977.html)
使用定界符;例如:许多基于文本的协议会在每个消息包的末尾追加一个换行符(或者一对回车换行符)
实现ProtocolEncoder编程要点
- MINA will call the encode function for all messages in the IoSession's write queue. Since our client will only write ImageRequest objects, we can safely cast message to ImageRequest.
MINA将对位于IoSession写队列中的所有消息调用encode函数。因为客户端只发送ImageRequest对象,我们可以安全地将message转为ImageRequest对象。
- We allocate a new ByteBuffer from the heap. It's best to avoid using direct buffers, since generally heap buffers perform better.
see http://issues.apache.org/jira/browse/DIRMINA-289)
我们从堆栈中分配新的ByteBuffer。最好避免使用direct buffers,通常堆栈中的buffers表现得更好。
- You do not have to release the buffer, MINA will do it for you, see http://mina.apache.org/report/1.1/apidocs/org/apache/mina/common/ByteBuffer.html
千万不要释放buffer,应由MINA自动释放。
- In the dispose() method you should release all resources acquired during encoding for the specified session. If there is nothing to dispose you could let your encoder inherit from ProtocolEncoderAdapter.
在dispose方法中,你应该释放指定的session编码期间获得的所有资源。如果没有东西要dispose,你可以让你的编码器从ProtocolEncoderAdapter派生。
- when it is impossible to calculate the length of the ByteBuffer beforehand, you can use an auto-expanding buffer by calling buffer.setAutoExpand(true);
如果不能事先计算出ByteBuffer的长度,你可以使用一个自动扩展的buffer,调用buffer.setAutoExpand(true)即可。
实现ProtocolDecoder编程要点
- everytime a complete message is decoded, you should write it to the ProtocolDecoderOutput; these messages will travel along the filter-chain and eventually arrive in your IoHandler.messageReceived method
每次只要一个完整的消息解出来,你就应该把它写入ProtocolDecoderOutput;这些消息将会在过滤器链(filter-chain)中流转,最终到达你的IoHandler.messageReceived方法中。
- you are not responsible for releasing the ByteBuffer
你不用负责释放ByteBuffer
- when there is not enough data available to decode a message, just return false
当没有接收到足够的数据去解消息时,仅返回false就行了。
- We store the state of the decoding process in a session attribute. It would also be possible to store this state in the Decoder object itself but this has several disadvantages:
我们在session的属性中存储解码过程的状态信息。这些信息也可以存储在解码器对象本身,但这样做有几个缺点:
- every IoSession would need its own Decoder instance
每个IoSession都需要它自己的解码器实例。
- MINA ensures that there will never be more than one thread simultaneously executing the decode() function for the same IoSession, but it does not guarantee that it will always be the same thread. Suppose the first piece of data is handled by thread-1 who decides it cannot yet decode, when the next piece of data arrives, it could be handled by another thread. To avoid visibility problems, you must properly synchronize access to this decoder state (IoSession attributes are stored in a ConcurrentHashMap, so they are automatically visible to other threads).
MINA确保对每一个IoSession同一时刻只有一个线程在执行decode() 函数——不允许多线程并发地执行解码函数,但它并不能保证每次解码过程都是同一线程在执行(两次解码用的可能是不同的线程)。假设第一块数据被线程1管理,这时还没接收到足够的数据以供解码,当接收到第二块数据时,被另一个线程管理,为了避免可视化方面的问题,你就必须适当地同步对解码器状态的访问(IoSession的属性存储在支持并发访问的ConcurrentHashMap中,因此它们对其他线程是自动可见的)。
- a discussion on the mailing list has lead to this conclusion: choosing between storing state in the IoSession or in the Decoder instance itself is more a matter of taste. To ensure that no two threads will run the decode method for the same IoSession, MINA needs to do some form of synchronization => this synchronization will also ensure you can't have the visibility problem described above.
在邮件列表的一次讨论得出这样的结论:选择存储状态信息到IoSession还是到解码器实例本身多少有些味道。为确保没有两个线程对同一IoSession运行解码方法,MINA需要做一些形式的同步 => 这种同步也将确保你不会碰到上面讨论的可视化问题。
see http://www.nabble.com/Tutorial-on-ProtocolCodecFilter,-state-and-threads-t3965413.html
- ByteBuffer.prefixedDataAvailable() is very convenient when your protocol uses a length-prefix; it supports a prefix of 1, 2 or 4 bytes.
当你的协议使用长度前缀时,ByteBuffer.prefixedDataAvailable() 用起来很方便,它支持1、2或4个字节的前缀。
- don't forget to reset the decoder state when you've decoded a response (removing the session attribute is another way to do it)
当你解码一个回应包时,别忘了重置解码器状态(也可以删除session的属性)。
分享到:
相关推荐
Apache Mina Server 2.0中文参考手册V1.0,Apache Mina2.0学习笔记(修订版)Apache Mina Server 2.0中文参考手册V1.0,Apache Mina2.0学习笔记(修订版)
**Android-MinaSocket:基于Mina的高效Socket长连接库** 在移动应用开发中,尤其是Android平台,实时性与稳定性是许多应用场景的核心需求,比如在线游戏、即时通讯、物联网设备等。在这种背景下,使用Socket进行长...
Mina和Socket是两种常见的网络通信框架和技术,它们在Java编程环境中被广泛使用。本篇文章将深入探讨如何使用Mina与Socket实现通信,并提供客户端和服务端的实现代码概述。 Mina(全称“MINA: Minimalistic ...
在本学习笔记中,我们将专注于MINA的子项目——FtpServer,它是实现FTP服务器功能的一个模块。 FTP(File Transfer Protocol)是一种广泛使用的互联网协议,用于在不同主机之间传输文件。Apache MINA FtpServer提供...
在示例中,你可能找到 `server` 和 `socket_client` 目录下的自定义 ProtocolHandler 实现。 5. **Server 端实现** 在 `server` 文件夹下,源代码会展示如何启动 Mina 服务器。首先,创建一个 Acceptor 来监听指定...
本文将深入探讨如何使用Mina来实现一个服务器以及对应的Socket客户端,从而进行消息传递。 **Mina 框架介绍** Mina提供了一个高级抽象层,允许开发者用类似处理Java IO的方式处理NIO(非阻塞I/O)。它简化了网络...
1. **下载使用的Jar包**:在开始Mina2.0的学习之前,你需要从Apache官网或其他可靠的源下载Mina的最新版本库。通常,这包括核心库和其他依赖库,如slf4j用于日志记录。 2. **工程创建配置**:创建一个新的Java项目...
学习Mina不仅涉及网络编程的基本概念,还需要掌握如何利用它的事件驱动模型和非阻塞I/O机制来提高系统的可伸缩性和性能。通过不断实践和深入学习,开发者可以更好地掌握Mina框架,构建出高效、稳定和可维护的网络...
如果是一个源码项目,开发者可以通过阅读和修改代码来学习MinaServer的实现原理,理解如何在Android环境中配置和使用Apache Mina框架。如果是APK文件,用户可以直接安装到兼容的Android设备上运行和测试MinaServer...
在本文中,我们将深入探讨Apache Mina的核心概念、设计模式以及如何使用它来实现基于Socket的通信。 **Apache Mina的核心概念:** 1. **Event-Driven模型**:Mina采用了事件驱动模型,当网络事件(如数据接收、...
mina简单示例,Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP、UDP/IP协议栈的通信框架(当然,也可以提供JAVA 对象的序列化服务、虚拟机管道通信服务等),Mina 可以帮助我们快速...
在学习Apache Mina FTPServer时,你需要了解以下关键知识点: 1. **FTP协议**:理解FTP的基本工作流程,包括控制连接和数据连接,以及ASCII和二进制模式的区别。 2. **Apache Mina API**:熟悉Mina的核心概念,如...
Socket通信和MINA长连接是网络编程中的两个关键概念,主要应用于服务器与客户端之间的数据交互。在移动应用开发,特别是需要实时推送功能时,这两种技术显得尤为重要。 **Socket通信** Socket,也称为套接字,是...
Apache Mina是一个强大的开源框架,专门用于构建高性能、高可扩展性的网络应用程序。Mina2.0是其一个重要的版本,提供了许多改进和新特性,使得开发者能够更轻松地处理网络通信任务,尤其是在Java NIO(Non-blocking...
1.mina socket客户度工程相关类,添加mina jar包后可独立运行。 2.mina若有空闲连接则使用已有连接,若无则新建mina连接; 3.mina空闲连接超过保活时间25分钟后,自动删除; 4.mina发送指令后,接收指定时长内收到的...
Socket Mina测试框架是一个强大的网络通信应用框架,主要用于简化Java应用程序与远程服务器之间的通信。它提供了高度可扩展和高性能的I/O处理模型,使得开发者能够更专注于业务逻辑,而不是底层的网络实现细节。Mina...
- `ProtocolCodecFactory`:编码和解码协议消息的工厂,MINA提供了一些标准的实现,如文本、二进制等。 7. **项目结构**:这个项目可能包含了服务端和客户端的源代码,以及必要的配置文件。服务端代码中会有创建`...
通过查看和运行这些代码,我们可以深入学习如何配置和实现Mina Server和Client的具体细节,例如如何定义处理器、如何处理网络事件以及如何进行数据编码和解码。 总的来说,这个实例提供了一个学习和实践Mina框架的...
基于Mina架构开发的可配置的Socket Server,后台采用MySql数据库,可以独立app部署或Tomcat Servlet部署,包括Socket Server全部实现代码,后台MySql数据备份文件,Java测试代码,android端测试代码和iOS端测试代码...