欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Socket通信封装MIna框架--含羞代放

程序员文章站 2022-12-21 12:11:46
[TOC] Mina异步IO使用的Java底层JNI框架,Mina提供服务端和客户端,将我们的业务解耦开发.真正做到高内聚低耦合的思想 核心类 IoService :Mina中将服务端和客户端都看成是服务,这里提供统一接口IoService,这个接口的作用就是用来处理套接字机制。也正是IoServi ......

mina异步io使用的java底层jni框架,mina提供服务端和客户端,将我们的业务解耦开发.真正做到高内聚低耦合的思想

核心类

  • ioservice :mina中将服务端和客户端都看成是服务,这里提供统一接口ioservice,这个接口的作用就是用来处理套接字机制。也正是ioservice来监听消息返回消息这些步骤,
    可以说ioservice就是我们mina中核心

  • ioprocessor:这个接口在另一个线程上,负责检查是否有数据在通道上读写,也就是说它也拥有自己的selector,这是与我们使用java nio 编码时的一个不同之处,通常在java nio 编码中,我们都是使用一个selector,也就是不区分ioservice与ioprocessor 两个功能接口。另外,ioprocessor 负责调用注册在ioservice 上的过滤器,并在过滤器链之后调用iohandler

  • iofilter : 定义了一些拦截器 , 和我们web中拦截器一样,用来横向拦截处理一些全局的操作(日志处理,编码处理)。其中我们必须注意的是加解密消息。
    作为一个好的框架肯定是有默认的拦截器的(textlinecodecfactory )。默认拦截器可以叫消息强制转换为string类型。毕竟string最通用

  • iohandler : 这个是我们处理消息的逻辑,前面的拦截器只是在接受是进行一些验证、翻译的功能。拿到数据之后我们需要做的事情就是在iohandler中

各个击破

ioservice

  • 首先我们已服务端niosocketacceptor为列,看看我们的服务类之间的结构依赖关系
    Socket通信封装MIna框架--含羞代放

  • ioservice是服务的鼻祖,无论在我们看来的服务端还是客户端都得继承它(间接继承)。在ioservice中我们会定义我们消息的处理过滤器(上文的拦截器),消息处理的业务类
    在上文简介中我们知道,这一步其实是ioprocessor来完成,那么ioprocessor在什么出现呢。比如mina框架中用来创建服务端类niosocketacceptor。他直接继承了abstractpollingioacceptor。而abstractpollingioacceptor类中根据参数创建了我们需要的ioprocessor.从而我们有了ioprocessor就可以执行消息间的通信了。
    Socket通信封装MIna框架--含羞代放

  • 所以过滤器、处理器实在我们服务启动之前配置好的。一旦启动成功就无法再修改了。我们服务端niosocketacceptor通过bind方法就可以绑定到指定端口上。我们这里的绑
    定实现了多态绑定。我们可以绑定多个服务。

/**
* {@inheritdoc}
*/
@override
public final void bind(iterable<? extends socketaddress> localaddresses) throws ioexception {
    if (isdisposing()) {
        throw new illegalstateexception("the accpetor disposed is being disposed.");
    }

    if (localaddresses == null) {
        throw new illegalargumentexception("localaddresses");
    }

    list<socketaddress> localaddressescopy = new arraylist<>();

    for (socketaddress a : localaddresses) {
        checkaddresstype(a);
        localaddressescopy.add(a);
    }

    if (localaddressescopy.isempty()) {
        throw new illegalargumentexception("localaddresses is empty.");
    }

    boolean activate = false;
    synchronized (bindlock) {
        synchronized (boundaddresses) {
            if (boundaddresses.isempty()) {
                activate = true;
            }
        }

        if (gethandler() == null) {
            throw new illegalstateexception("handler is not set.");
        }

        try {
            set<socketaddress> addresses = bindinternal(localaddressescopy);

            synchronized (boundaddresses) {
                boundaddresses.addall(addresses);
            }
        } catch (ioexception | runtimeexception e) {
            throw e;
        } catch (exception e) {
            throw new runtimeioexception("failed to bind to: " + getlocaladdresses(), e);
        }
    }

    if (activate) {
        getlisteners().fireserviceactivated();
    }
}

在上面我们可以看到bind最后是去激活对应的监听器。我们一个ioserver处理一个线程中的消息。我们监听器就是监听线程内的消息。每一次的绑定都会有不同的监听器、iosession去专门处理消息之间的通信。我们可以通过iosession设置一些请求数据完成数据的权限验证。

  • 在服务创建的时候我们正常需要设置iosession的一些配置。通过getsessionconfig方法获取iosessionconfig。里面设置参数常用如下:
    • setreadbuffersize : 设置读取数据的缓冲区大小
    • setminreadbuffersize: 设置缓冲区最大值
    • setmaxreadbuffersize: 设置缓冲区最小值
    • setthroughputcalculationinterval: 设置通道计算时间 默认3s
    • setidletime(idlestatus status, int idletime): status 设置是一方还是双方 , idletime 是超过多久就会进入空闲状态
ioacceptor acceptor=new niosocketacceptor();    
acceptor.getsessionconfig().setreadbuffersize(2048);    
acceptor.getsessionconfig.setidletime(idlestatus.both_idle,10);

iofilter

在ioservice中有获取filter链的一个方法 defaultiofilterchainbuilder getfilterchain() , 我们需要做的就是定义过滤器,然后通过该方法获取过滤链加入到请求链上。
我们自定义过滤器也很简单,只需要继承iofilteradapter这个类就好了。

  acceptor.getfilterchain().addlast("codec",  new protocolcodecfilter(new textlinecodecfactory( 
charset.forname("utf-8"),linedelimeter.windows.getvalue(),linedelimiter. windows.getvalue()))    
);    

textlinecodecfactory 这个类是mina提供的编解码工厂,这个工厂的特性是以换行符'\r\n'为结束通信的标志。也就是说如果我们传递消息没有换行符,另外一段会继续
接受消息知道接受到'\r\n'才会接受,并把接受到的消息通过编解码器转到iohandler层供业务层处理。(这里博主被坑在这里了)

iohandler

  • 到了这一步,我们的通信基本就已经完成了。剩下的事情已经和mina基本没多大关联了。我们将在这里处理业务逻辑,使用到的就是handler提供的接收消息和发送消息两个功能。
    这里我们需要注意的是handler提供messagereceivedmessagesent并不是字面意思。前者就是消息的接受,但是后者并不是消息的发送。我们常用的发送消息是session.write方法。

总结

今天我们了解了mina工作的流程,主要就是iofilter和iohandler实现消息的通信 。 千里之行始于足下,一点一点的进步。下面贴出一份总结的图谱帮助我们理解mina流程

Socket通信封装MIna框架--含羞代放

加入战队

# 加入战队

微信公众号

Socket通信封装MIna框架--含羞代放