详解Java Socket通信封装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为列,看看我们的服务类之间的结构依赖关系

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

所以过滤器、处理器实在我们服务启动之前配置好的。一旦启动成功就无法再修改了。我们服务端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提供messageReceived和messageSent并不是字面意思。前者就是消息的接受,但是后者并不是消息的发送。我们常用的发送消息是session.write方法。

总结

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

以上就是详解Java Socket通信封装MIna框架的详细内容,更多关于Java Socket通信封装MIna框架的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java Socket实现简易聊天室

    Java-Socket编程实现简易聊天室(TCP),供大家参考,具体内容如下 实现一个服务器接收多个客户端 测试: 首先启动服务器,然后启动三个客户端,输入三个不同的用户名,分别在聊天室发消息 看其他客户端是否能接收到消息 效果如下图: 一号发消息 可以在二号和三号客户端接收到消息 服务器设计 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import ja

  • Java基于TCP协议socket网络编程的文件传送的实现

    先了解一下socket基本概念 socket也叫套接字: 是指在网路中不同主机上的应用进程之间,进行双向通信的端点的抽象. 简单理解就是: 两个主机之间要通信,就需要知道彼此的ip,端口号等信息,而一台主机这些信息的集合: 就可以理解为一个端点,即为套接字 双方通过套接字作为一种坐标,建立信息通道,形成连接(两点连接一条直线) 简单理解了套接字的概念后,来看看如何通过java socket编程来实现 两台主机文件的接收与发送: 代码如下: 发送方: import java.io.*; impor

  • Java实现简单的socket通信教程

    今天学习了一下java如何实现socket通信,感觉难点反而是在io上,因为java对socket封装已经很完善了. 今天代码花了整个晚上调试,主要原因是io的flush问题和命令行下如何运行具有package的类,不过最后问题基本都解决了,把代码贴出来供大家参考 server public class TcpServer { public static void main(String[] args) throws Exception { ServerSocket server = new S

  • Python连接Java Socket服务端的实现方法

    java服务端单线程示例 import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; /** * Server */ public class Server { public static void main(String[] args) throws IOException {

  • JAVA实现SOCKET多客户端通信的案例

    一.ServerSocket 1.为了方便调试,先创建一个界面用于显示客户端连接信息 基于javafx包写的一个简单界面! javafx.scene.control.TextArea ta = new javafx.scene.control.TextArea(); @Override public void start(Stage primaryStage) throws Exception { scene = new Scene(ta,450,200); primaryStage.setTi

  • Java 实现简单Socket 通信的示例

    目录 1. 传输层协议 2. TCP 示例 2.1 示例效果 2.2 服务端程序代码 3. UDP 示例 3.1 服务端程序代码 3.2 客户端程序代码 Java socket 封装了传输层的实现细节,开发人员可以基于 socket 实现应用层.本文介绍了 Java socket 简单用法. 1. 传输层协议 传输层包含了两种协议,分别是 TCP (Transmission Control Protocol,传输控制协议) 和 UDP (User Datagram Protocol,用户数据报协

  • Java通过Socket实现简单多人聊天室

    本文实例为大家分享了Java通过Socket实现多人聊天室的具体代码,供大家参考,具体内容如下 Socket可以实现网络上两个程序通过双向通道进行数据的交换,此外它是Java中网络TCP/IP协议的封装,例如可以进行网络通信等等,下面我们就来简单写一下多人聊天室. 首先来分析一下要实现的流程 首先建立一个服务器端,构建ServerSocket并绑定端口 创建socket客户端,连接到指定ip以及其端口 然后使用accept阻塞接收socket发出的连接请求 获取连接后的socket客户端的输入流

  • Java 基于TCP Socket 实现文件上传

    文件上传过程一个单向Socket通信过程.客户端通过文件输入流读取文件,然后从Socket获取输出流写入数据.服务端从Socket中获得输入流,然后写入文件输出流,写入数据完成则上传完成. 服务端UploadServer: public class UplaodServer { public static void main(String []args){ try( // 创建一个ServerSocket监听8080端口的请求 // ServerSocket 实现了 AutoCloseable接

  • java利用socket通信实现Modbus-RTU通信协议的示例代码

    Modbus Modbus是一种串行通信协议.Modbus 一个工业上常用的通讯协议.一种通讯约定.Modbus协议包括RTU.ASCII.TCP.其中MODBUS-RTU最常用,比较简单,在单片机上很容易实现. 简单分析Modbus-RTU报文 37 03 10 3F 80 00 00 00 00 00 00 3F 80 00 00 40 40 00 00 24 dd(十六进制) 37:从站地址 ,03:功能码,10:读取的字节数,24 dd:crc校验码.其它就是传送的数据. 4G DTU(

  • 详解Java Socket通信封装MIna框架

    核心类 IoService :Mina中将服务端和客户端都看成是服务,这里提供统一接口IoService,这个接口的作用就是用来处理套接字机制.也正是IoService来监听消息返回消息这些步骤,可以说IoService就是我们Mina中核心 IoProcessor:这个接口在另一个线程上,负责检查是否有数据在通道上读写,也就是说它也拥有自己的Selector,这是与我们使用JAVA NIO 编码时的一个不同之处,通常在JAVA NIO 编码中,我们都是使用一个Selector,也就是不区分Io

  • 详解Java基础之封装

    目录 Java基础知识(封装) 封装 封装的目的 封装的好处 封装的步骤 封装的例子 总结 Java基础知识(封装) 封装 那封装是什么呢? 在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部分包装.隐藏起来的方法. 封装的目的 直接通过操控类对象来达到目的,不需要对具体实现十分了解,使类属性和方法的具体实现对外不可见.不但方便还起到了保护作用. 封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段. 适当的封装可

  • 详解Java中的封装、继承、多态

    封装 在如何理解面向对象这篇文章中,提到所谓的封装就是"功能都给你做好了,你不必去理解它是怎么写出来的,直接使用即可.".但你得清楚一点,那就是这句话是相对于使用者来说的,而作为开发者,封装就得我们自己来干. 那么作为开发者,我们应该如何去封装呢?其实你应该反过来问,他们应该如何去使用,这样一想会简单很多,作为使用者,自然是希望越简单越好,也就是说,一些复杂的东西,我们不应该让使用者去操作,那也就是说我们应该把复杂的,以及不必要的参数给它封死,不让使用者去操作. 为什么不让使用者去操作

  • 详解Java如何通过Socket实现查询IP

    目录 背景 使用示例 应用例子 应用服务器 获取客户端的IP地址 向客户端发送消息 测试应用程序 建立一个客户端应用程序 运行应用程序 在后台发生了什么 总结 在本文中,我们来学习下如何找到连接到服务器的客户端计算机的IP地址.我们将创建一个简单的客户端-服务器场景,让我们探索用于TCP/IP通信的java.net API. 背景 Java应用程序使用套接字在互联网上进行通信和发送数据.Java为客户端应用程序提供了java.net.Socket类. java.net.ServerSocket类

  • 详解java调用存储过程并封装成map

    详解java调用存储过程并封装成map 本文代码中注释写的比较清楚不在单独说明,希望能帮助到大家, 实例代码: public List<Map<String , Object>> doCallProcedure(String procedureString,String[] parameters) throws PersistentDataOperationException { if (!isReady ()) { throw new PersistentDataOperatio

  • 详解Java单元测试之Junit框架使用教程

    目录 单元测试 Junit单元测试框架 单元测试快速入门 单元测试 单元测试就是针对最小的功能单元编写测试代码,Java程序最小的功能单元是方法,因此,单元测试就是针对Java方法的测试,进而检查方法的正确性 目前测试方法是怎么进行的,存在什么问题? 1.只有一个main方法,如果一个方法的测试失败了,其他方法测试会受到影响 2.无法得到测试的结果报告,需要程序员自己去观察测试是否成功 3.无法实现自动化测试 Junit单元测试框架 1.Junit是使用Java语言实现的单元测试框架,它是开源的

  • 详解java设计模式之六大原则

    一.单一职责原则 1.单一职责定义 单一职责原则:一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因. 单一职责原则告诉我们:一个类不能太"累"!在软件系统中,一个类承担的职责越多,它被复用的可能性就越小,而且一个类承担的职责过多,就相当于将这些职责耦合在一起,当其中一个职责 变化时,可能会影响其他职责的运作,因此要将这些职责进行分离,将不同的职责封装在不同的类中,即将不同的变化原因封装在不同的类中,如果多个职责总是同时发生改变则可将它们封

  • 详解Java TCC分布式事务实现原理

    概述 之前网上看到很多写分布式事务的文章,不过大多都是将分布式事务各种技术方案简单介绍一下.很多朋友看了还是不知道分布式事务到底怎么回事,在项目里到底如何使用. 所以这篇文章,就用大白话+手工绘图,并结合一个电商系统的案例实践,来给大家讲清楚到底什么是 TCC 分布式事务. 业务场景介绍 咱们先来看看业务场景,假设你现在有一个电商系统,里面有一个支付订单的场景. 那对一个订单支付之后,我们需要做下面的步骤: 更改订单的状态为"已支付" 扣减商品库存 给会员增加积分 创建销售出库单通知仓

  • 详解php中流行的rpc框架

    什么是RPC框架? 通常我们调用一个php中的方法,比如这样一个函数方法: localAdd(10, 20),localAdd方法的具体实现要么是用户自己定义的,要么是php库函数中自带的,也就说在localAdd方法的代码实现在本地,它是一个本地调用! 远程调用原理 比如 A (client) 调用 B (server) 提供的remoteAdd方法: 1.首先A与B之间建立一个TCP连接: 2.然后A把需要调用的方法名(这里是remoteAdd)以及方法参数(10, 20)序列化成字节流发送

  • 详解Java网络编程

    一.网络编程 1.1.概述 1.计算机网络是通过传输介质.通信设施和网络通信协议,把分散在不同地点的计算机设备互连起来,实现资源共享和数据传输的系统.网络编程就就是编写程序使联网的两个(或多个)设备(例如计算机)之间进行数据传输.Java语言对网络编程提供了良好的支持,通过其提供的接口我们可以很方便地进行网络编程. 2.Java是 Internet 上的语言,它从语言级上提供了对网络应用程 序的支持,程序员能够很容易开发常见的网络应用程序. 3.Java提供的网络类库,可以实现无痛的网络连接,联

随机推荐