Mina源码阅读笔记(五)—Mina对连接的操作IoSession

Apache Mina 源码再读4 IoSession.write()源码剖析 Apache Mina IoSession.write(Object message) 写出数据流程小结: 1、Processor 线程首选轮询newSessions中每一个IoSession. 然后,把IoSession 放到IoService 的managedSessions中进行管理追踪。 2、当IoSession.write(Object message) 调用时,会创建一个WriteFuture 对象,并创建一个WriteRequest 对象,把这个对象增加到每一个IoSession关联的Wr 阅读详情

IoSession是Mina管理两端的一个重要部分,也是Mina的核心,Session具有了生命周期的概念,它的生命周期和连接时紧密相关的,这点在后面的介绍中会涉及。另外,好像hibernate中也有session也有生命周期(真的是好久没有用了,连hibernate有里session是干嘛的都想不起来了)。

在读源码之前,我们还是先了解下IoSession的作用和一些基本概念。IoSession的主要作用有如下一些:

l  管理连接。注意,这里的管理连接并不是直接去控制我们上次讲的最底层的连接acceptor和connector。如果acceptor和connector建立的一条管道,那session就是在管道内的管理者,他是没有办法将管道对半拆分开的,他只能从内部阻断两边的通信。管理连接还有部分就是可以配置缓冲区的大小,闲置时间等等。

l  存储信息。和web里的session一样,这里的session也有存储attribute的功能,不过一般来说,这里存储的都是和连接有关的东西,并不会像web开发一样存一些业务上的东西。

l  驱动读写操作。我不知道用驱动这个词是否合适,那个例子来说,session.write。

l  统计功能。Session还记录了连接中的byte、message等数量。

Session在使用中是通过ConnectionFuture获得的:

1 ConnectFuture future = connector.connect(new InetSocketAddress(
2                     HOST, PORT));// 创建连接
3             future.awaitUninterruptibly();// 等待连接创建完成
4             session = future.getSession();// 获得session

说完作用,就是session的状态了,我们读源码的时候,也会跟着session的状态来读:

  • Connected : the session has been created and is available
  • Idle : the session hasn't processed any request for at least a period of time (this period is configurable)
    • Idle for read : no read has actually been made for a period of time
    • Idle for write : no write has actually been made for a period of time
    • Idle for both : no read nor write for a period of time
  • Closing : the session is being closed (the remaining messages are being flushed, cleaning up is not terminated)
  • Closed : The session is now closed, nothing else can be done to revive it.

注意,这里的最开始的connect,最后的closed这些都说的是acceptor和connector之间的操作,是他们的状态来影响session的状态。和hibernate不一样,那个的操作也是session自己的(session.close等),这里的session是没办法控制通道的。

了解完了基础的,我们来看看代码层面的实现,在org,apache.mina.core.session包中主要实现了IoSession的相关功能。我们从IoSession这个接口开始看起:

内容比较多,比之前的那几篇都难多了。我们还是按照上图画出来的方框对这些方法进行分分类,看看是不是跟我们之前分析的一样:

红色:得到一系列配置等。我们说了session是mina的核心。

蓝色:驱动读写操作。

绿色:管理连接。

黑色:存储功能,是不是和JSP里的session很像。

橘色:统计数据。

有些没有框上的并不是说不属于这里面,而是有些我确实不了解,有些是比较难划分,具体的含义可以看源码中,都有说明。

了解完IoSession的最基本功能之后,我们要看看它的具体实现类AbstractIoSession。看具体实现之前,我们先看看这个类关联了哪些比较重要的引用:

01 private final IoHandler handler;
02  
03     protected IoSessionConfig config;
04  
05       private final IoService service;
06  
07     private static final AttributeKey READY_READ_FUTURES_KEY = newAttributeKey(AbstractIoSession.class,
08             "readyReadFutures");
09 private static final IoFutureListener<CloseFuture> SCHEDULED_COUNTER_RESETTER;
10  
11   private static final WriteRequest CLOSE_REQUEST = new DefaultWriteRequest(new Object());
12  
13     private IoSessionAttributeMap attributes;
14  
15     private WriteRequestQueue writeRequestQueue;
16  
17 private WriteRequest currentWriteRequest;
18  
19 private final CloseFuture closeFuture = new DefaultCloseFuture(this);

在上面的代码中,我们有熟悉的handler,这里我们也可以稍微明确一下handler和session之间的关系了,每次我们在创建服务端和客户端的时候,都必须设置一个handler,如果不设置则报异常,handler里主要处理seesion各种状态时的业务。Service用来管理session。CloseFutrue用来设置通道的关闭,在上面我们已经说过,session的关闭是通过closefuture来操作的。

这些成员变量中,除了我们见过的handler和future,凡是带有write的都来自org.apache.mina.core.write包,这个包作为一个内部的工具类,在session的写操作中起到辅助作用。其他类均来自org.apache.mina.core.session中,这些类组成都比较简单,但都是要了解AbstractIoSession之前,我们要对这里提到的这些对象有所了解。

首先是ioSessionConfig,和它的具体实现AbstractIoSessionCnfig:

从上面的图我们很容易就能看到mina的一些默认传输配置,当然这些数字都不是随便写的,为什么最小要64,最大是65535,我相信计算机网络相关课程里应该都会有涉及。

接下来是IoSessionAttributeMap接口,这个接口主要作用就是规定了get、set、remove Attribute的方法。注意存储在session中的变量是一种map关系的变量(key-value),所以我们也很容易明白这个接口命名时为什么后面要多个map出来。至于这个类的实现,它隐藏的很好,放在了一个内部类中。具体可以看IoSessionDataStructureFactory这个接口,这个接口主要是为了这个map形势提供数据结构和规定基本操作。至于这个session中map的底层实现则用了ConcurrentHashMap来做容器,这部分具体可以看内部类DefaultIoSessionAttributeMap。

还有一个就是AttributeKey,这个类主要重写equals方法和hashCode方法,为了将session中的key和对应的session联系起来。因为一个项目中可能有多个session,而不同session中的key可能会相同,所以在构造key和hash的时候会将session也考虑进去。

1 public AttributeKey(Class<?> source, String name) {
2         this.name = source.getName() + '.' + name + '@' + Integer.toHexString(this.hashCode());
3     }

现在我们可以看AbstractIoSession了。主要看读写操作,其他操作都是统计和配置稍稍看过即可:

01 public final ReadFuture read() {
02         if (!getConfig().isUseReadOperation()) {
03             throw new IllegalStateException("useReadOperation is not enabled.");
04         }
05  
06         Queue<ReadFuture> readyReadFutures = getReadyReadFutures();
07         ReadFuture future;
08         synchronized (readyReadFutures) {
09             future = readyReadFutures.poll();
10             if (future != null) {
11                 if (future.isClosed()) {
12                     // Let other readers get notified.
13                     readyReadFutures.offer(future);
14                 }
15             } else {
16                 future = new DefaultReadFuture(this);
17                 getWaitingReadFutures().offer(future);
18             }
19         }
20  
21         return future;
22     }

采用队列进行读取,这里只用了Queue,没有用concurrent中的那些同步队列,而是用了synchronized关键字来处理同步,主要是我们要明白这里要同步的不是队列里的内容,而是读的这个过程,session都是独立的,所以一个session内一个队列无论怎么抢还是能排除顺序的。所以对于读操作来说,主要是要保证在读一条的时候,不能有其他线程再读。

下面是写操作:

01 public WriteFuture write(Object message, SocketAddress remoteAddress) {
02         if (message == null) {
03             throw new IllegalArgumentException("Trying to write a null message : not allowed");
04         }
05  
06         // We can't send a message to a connected session if we don't have
07         // the remote address
08         if (!getTransportMetadata().isConnectionless() && (remoteAddress != null)) {
09             throw new UnsupportedOperationException();
10         }
11  
12         // If the session has been closed or is closing, we can't either
13         // send a message to the remote side. We generate a future
14         // containing an exception.
15         if (isClosing() || !isConnected()) {
16             WriteFuture future = new DefaultWriteFuture(this);
17             WriteRequest request = new DefaultWriteRequest(message, future, remoteAddress);
18             WriteException writeException = new WriteToClosedSessionException(request);
19             future.setException(writeException);
20             return future;
21         }
22  
23         FileChannel openedFileChannel = null;
24  
25         // TODO: remove this code as soon as we use InputStream
26         // instead of Object for the message.
27         try {
28             if ((message instanceof IoBuffer) && !((IoBuffer) message).hasRemaining()) {
29                 // Nothing to write : probably an error in the user code
30                 throw new IllegalArgumentException("message is empty. Forgot to call flip()?");
31             } else if (message instanceof FileChannel) {
32                 FileChannel fileChannel = (FileChannel) message;
33                 message = new DefaultFileRegion(fileChannel, 0, fileChannel.size());
34             } else if (message instanceof File) {
35                 File file = (File) message;
36                 openedFileChannel = new FileInputStream(file).getChannel();
37                 message = newFilenameFileRegion(file, openedFileChannel, 0, openedFileChannel.size());
38             }
39         } catch (IOException e) {
40             ExceptionMonitor.getInstance().exceptionCaught(e);
41             return DefaultWriteFuture.newNotWrittenFuture(this, e);
42         }
43  
44         // Now, we can write the message. First, create a future
45         WriteFuture writeFuture = new DefaultWriteFuture(this);
46         WriteRequest writeRequest = newDefaultWriteRequest(message, writeFuture, remoteAddress);
47  
48         // Then, get the chain and inject the WriteRequest into it
49         IoFilterChain filterChain = getFilterChain();
50         filterChain.fireFilterWrite(writeRequest);
51  
52         // TODO : This is not our business ! The caller has created a
53         // FileChannel,
54         // he has to close it !
55         if (openedFileChannel != null) {
56             // If we opened a FileChannel, it needs to be closed when the write
57             // has completed
58             final FileChannel finalChannel = openedFileChannel;
59             writeFuture.addListener(new IoFutureListener<WriteFuture>() {
60                 public void operationComplete(WriteFuture future) {
61                     try {
62                         finalChannel.close();
63                     } catch (IOException e) {
64                         ExceptionMonitor.getInstance().exceptionCaught(e);
65                     }
66                 }
67             });
68         }
69  
70         // Return the WriteFuture.
71         return writeFuture;
72     }

这里面有个instanceof FileChannel和File是不是感到有点儿奇怪,mina不是写出去的是IoBuffer么,怎么现在又可以写文件了。Mina作为一个封装好的框架,自然可以直接做文件的传输,这里面会有相应的handler来处理这些业务。

Session部分最主要的就是了解他的生命周期以及相关联的那些引用,这里我们可以看到与读写最密切的就是Future了,所以这部分,就是我下篇会写的主题。


Mina 长连接实践 - Mina介绍最近项目需要使用长连接,而Mina应该是个不错的选择。个人在Mina的长连接的集成过程中碰到一些问题解决,现在和大家探讨下。言归正传,要使用Mina首先需要看看Mina的官网,特别是他的开发文档需要阅读下(http://mina.apache.org/mina-project/documentation.html)。个人觉得以下二张图是比重要的(来自于http://mina.apac 阅读详情

相关推荐

基于迁移学习的花卉识别系统

本研究采用了预训练的经典深度学习模型,包括ResNet、AlexNet和VGG,通过微调的方式在Oxford-102数据集和一个自制花卉数据集上进行训练,并对图像进行了多种数据增强操作,以提高模型的泛化能力,致力于实现花卉的高效分类。

m0_71146337的博客 2378

FTP错误详解及解决方案

http://www.cjzzc.com/article/227.html https://blog.youkuaiyun.com/gulingeagle/article/details/6019668

Lemon_MY的博客 1302

VS Code下载安装与使用教程

VSCode下载安装与使用教程

weixin_46713695的博客 4万+

Mina框架IoSession详解

通过Mina官 网文档,我们可以看到,有如下几个状态: Connected : the session has been created and is available Idle : the session hasn’t processed any request for at least a period of time (this period ...

weixin_33978044的博客 1333

PCIe(Peripheral Component Interconnect Express)的带宽和速率

PCIe带宽与速率解析 PCIe的速率指物理层传输速度(GT/s),而带宽是实际有效数据吞吐量(GB/s)。不同PCIe版本采用不同编码方式: PCIe 1.0-2.0:8b/10b编码(80%效率) PCIe 3.0+:128b/130b编码(≈98.5%效率) 单向峰值带宽速查(单位:GB/s): 版本 x1 x4 x8 x16 PCIe3 0.98 3.94 7.88 15.75 PCIe4 1.97 7.88 15.75 31.51 PCIe5 3.94 15.75 31.51 63.02 PCIe

MHD0815的博客 347

n8n智能体开发:Microsoft Outlook 节点

使用 Microsoft Outlook 节点可以自动化 Microsoft Outlook 工作流程,并将其与其他应用程序集成。n8n 内置支持多种 Microsoft Outlook 功能,包括创建、更新、删除和获取文件夹、邮件及草稿等操作。

王国平的博客 570

mina学习笔记四:交互的核心IoSession

这一章讲的就是IoSession,session这个词做web应用的

Yoara的备忘录 2万+

OpenClaw进阶实战(五):多模态能力扩展——让OpenClaw看懂图片、听懂语音

本文介绍了如何在OpenClaw中实现多模态能力,包括图像文字识别(OCR)、图像描述和语音识别(ASR)三种技能。通过PaddleOCR、BLIP和Whisper等开源工具,可以本地化部署这些功能,保护数据隐私。文章详细展示了三个独立技能模块的实现代码,并提出了一个"多模态智能管家"方案,能自动识别消息类型(文本/图片/语音)并调用相应处理技能。该方案适用于电商客服、会议纪要等真实业务场景,使AI助手具备"眼睛"和"耳朵"的多模态交互能力。

PeterPan的博客 160

Mina源码阅读笔记(三)-Mina的连接IoAccpetor

其实在mina的源码中,IoService可以总结成五部分service责任、Processor线程处理、handler处理器、接收器和连接器,分别对应着IoService、IoProcessor、IoHandler、IoAcceptor和IoConnector。在代码的中有如下包跟IoService关系密切: 1 org.apache.mina.core.se

undoner 1267

【AI for Medecine】吴恩达医学图像AI专项课程(诊断、预测、治疗)

近期需要简单了解AI4Science上的一些应用,看到吴恩达大佬的专项课程,于是开始来个“全面”的了解--医学人工智能(诊断、预测、治疗)。

图挖掘领域,新晋砖家 ☞ 未来可期,欢迎和静静一起学习交流吖 774

【光子 AI 】应用 LangGraph 的核心模型和算法原理,完整实现一个极简版的 Agent 开发框架源代码,并给出具体的应用测试实际项目案例

下面给出一个“极简版 LangGraph 风格 Agent 框架”的完整可运行实现:用 有向图 + 状态(State) + 节点(Node) + 条件路由(Conditional Edge) + 循环(Loop) + Checkpoint 这一套核心模型/算法,把 Agent 组织成可编排、可测试的状态机工作流(这正是 LangGraph 的核心抽象之一:以 StateGraph 组织节点,节点读写共享状态,边做路由与循环,并支持持久化/回放)。 参考概念来源:LangGraph 官方文档对 “StateG

AI天才研究院 270

Mina源码阅读笔记(四)—Mina的连接IoConnector

mina

smithdoudou88的专栏 1503

【测开求职】面试题:数据结构 吐血整理

本篇文章是笔者为准备研究生复试以及校招而写,因此主要针对问答,注重理解,而不在于细节计算。涵盖考研范围内的所有知识内容,读者可以先查看上面的链接走一遍数据结构的整体框架结构。其中,重点难点以及易混淆的知识点,笔者用其他近30篇文章进行了详述,在知识点处贴好了链接,有需要的可以查阅。

vector的博客 7065

MINA教程详解

1. Mina官网资料 Mina官网是学习mina最重要的地方:Apache Mina Mina官网上有教你快速上手的quick start:《Quick Start》 Mina官网提供了User Guide,这个手册包含了很多概念和示例:《User Guide》 2. Mina的应用博客 Mina基于NIO开发 中间有个重要的桥梁缓冲区,了解两者不同:《IoBuffer和ByteBuffer》 Mina实现自定义协议的通信、对通信的一些思考:《Mina实现自定义协议通信》、《Tcp传输下的..

应无所住而生其心 994

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Mina源代码阅读—概述

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34417635的博客 131

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Mina系列文章索引

作者:Gaischen 地址:http://my.oschina.net/ielts0909/blog/92716 写了很多关于Apache Mina的文章,为了方便大家阅读,我将关于mina的一些文章做点儿索引。 Mina官网资料—————————————————————– Mina官网是学习mina最重要的地方:Apache Mina Mina官网上有教你快速上手的quick star

centre10的专栏 2572

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Mina源代码分析—概述

Mina是Apache旗下非常著名的开源的网络编程框架,支持TCP、UDP以及其他的一些网络通讯协议,具体的使用说明可以参照UserGuide(http://...)。本文不再介绍Mina的使用,而是记录在阅读源码过程中的一些心得。我们知道网络编程的一般流程如下: 1. 监听端口,等待连接 2. 建立连接 3. 建立线程,读取并处理内容 4. 关闭连接 Mina的处理流程在逻辑上与上面所

坐禅小和尚的专栏 1763

IOServer开源项目介绍及源码分析

<br />IOServer是国人写的一个仿MINA的轻量级服务器框架。最近因为使用MINA的缘故,阅读了IOServer的源码,顺便熟悉了J2SE NIO部分。<br /> <br />IOServer的设计目标是手机网游服务器框架。支持TCP协议。<br /> <br />这个框架的使用方法和MINA类似;它有一个ProtocolHandler和IOHandler,没有MINA的FilterChain;<br /> <br />基本的流程是:创建Config,设定端口、ProtocolHandler和I

Pi的空间 3305

MINA框架解析:核心架构、面试题与性能优化

网络应用框架是构建高性能分布式系统的关键技术,其中MINA作为基于Java NIO的经典框架,通过分层架构设计显著降低了网络编程复杂度。其核心原理包括I/O服务层、过滤器链层和业务逻辑层的协同工作,特别适合金融交易、电商秒杀等高并发场景。在实际工程中,合理配置线程模型和缓冲区大小对提升吞吐量至关重要,而过滤器链机制则为协议转换等需求提供了灵活扩展点。本文通过典型面试题解析和调优案例,深入探讨如何避免内存泄漏、优化连接管理等实战经验,为开发者提供从入门到精通的系统学习路径。

weixin_31315567的博客 212

openfire 开发时输出xml到控制台

openfire 开发时输出xml到控制台 标签: openfire调试 2016-02-15 09:38 448人阅读 评论(0) 收藏 举报  分类: IM(11)  版权声明:本文为博主原创文章,未经博主允许不得转载。 openfire以前的版本,可以在调试时,直接把xml输出到控制台。但现在不能输出了。我跟了下源码。调试输出是由插

王人冉的博客 331

MINA2.0原理

转自:http://blog.youkuaiyun.com/liuzhenwen/article/details/5894279 客户端通信过程  1.通过SocketConnector同服务器端建立连接  2.链接建立之后I/O的读写交给了I/O Processor线程,I/O Processor是多线程的  3.通过I/O Processor读取的数据经过IoFilterChain里所有配

xianymo的专栏 755
上一篇: 使用java测试网络连通性
下一篇: RISC和CISC的区别
meng0911
博客等级 码龄15年 15粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值