网络通信应用框架apache mina(一)

本文介绍了Apache Mina网络通信框架的基本使用方法,通过搭建简单的TCP服务器和客户端演示了Mina如何帮助开发者快速构建高性能的网络应用。文章覆盖了Mina的主要组件和服务流程,以及如何配置编解码器和处理器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP、UDP/IP协议栈的通信框架(当然,也可以提供JAVA 对象的序列化服务、虚拟机管道通信服务等),Mina 可以帮助我们快速开发高性能、高扩展性的网络通信应用,Mina 提供了事件驱动、异步(Mina 的异步IO 默认使用的是JAVA NIO 作为底层支持)操作的编程模型。Mina 主要有1.x 和2.x 两个分支,这里我们讲解最新版本2.0,如果你使用的是Mina 1.x,那么可能会有一些功能并不适用。学习本文档,需要你已掌握 JAVA IO、JAVA NIO、JAVASocket、JAVA 线程及并发库(java.util.concurrent.*)的知识。Mina 同时提供了网络通信的Server 端、Client 端的封装,无论是哪端,Mina 在整个网通通信结构中都处于如下的位:

这里写图片描述

可见Mina 的API 将真正的网络通信与我们的应用程序隔离开来,你只需要关心你要发送、接收的数据以及你的业务逻辑即可。同样的,无论是哪端,Mina 的执行流程如下所示:

这里写图片描述

(1.) IoService:这个接口在一个线程上负责套接字的建立,拥有自己的Selector,监听是否有连接被建立。
(2.) IoProcessor:这个接口在另一个线程上负责检查是否有数据在通道上读写,也就是说它也拥有自己的Selector,这是与我们使用JAVA NIO 编码时的一个不同之处,通常在JAVA NIO 编码中,我们都是使用一个Selector,也就是不区分IoService与IoProcessor 两个功能接口。另外,IoProcessor 负责调用注册在IoService 上的过滤器,并在过滤器链之后调用IoHandler。
(3.) IoFilter:这个接口定义一组拦截器,这些拦截器可以包括日志输出、黑名单过滤、数据的编码(write 方向)与解码(read 方向)等功能,其中数据的encode 与decode是最为重要的、也是你在使用Mina 时最主要关注的地方。
(4.) IoHandler:这个接口负责编写业务逻辑,也就是接收、发送数据的地方。


1.简单的TCPServer:
    (1) 第一步:编写IoService按照上面的执行流程,我们首先需要编写IoService,IoService 本身既是服务端,又是客户端,我们这里编写服务端,所以使用IoAcceptor 实现,由于IoAcceptor 是与协议无关的,因为我们要编写TCPServer,所以我们使用IoAcceptor 的实现NioSocketAcceptor,实际上底层就是调用java.nio.channels.ServerSocketChannel 类。当然,如果你使用了Apache 的APR 库,那么你可以选择使用AprSocketAcceptor 作为TCPServer 的实现,据传说Apache APR库的性能比JVM 自带的本地库高出很多。那么IoProcessor 是由指定的IoService 内部创建并调用的,我们并不需要关心。
public class MyServer {
    main方法:
    IoAcceptor acceptor=new NioSocketAcceptor();
    acceptor.getSessionConfig().setReadBufferSize(2048);
    acceptor.getSessionConfig.setIdleTime(IdleStatus.BOTH_IDLE,10);
    acceptor.bind(new InetSocketAddress(9123));
}
这段代码我们初始化了服务端的TCP/IP 的基于NIO 的套接字,然后调用IoSessionConfig设置读取数据的缓冲区大小、读写通道均在10 秒内无任何操作就进入空闲状态。

(2) 第二步:编写过滤器
这里我们处理最简单的字符串传输,Mina 已经为我们提供了TextLineCodecFactory 编解码器工厂来对字符串进行编解码处理。
acceptor.getFilterChain().addLast("codec",
  new ProtocolCodecFilter(
   new TextLineCodecFactory(Charset.forName("UTF-8"),
   LineDelimeter.WINDOWS.getValue(),
   LineDelimiter. WINDOWS.getValue()
   )
  )
);
这段代码要在acceptor.bind()方法之前执行,因为绑定套接字之后就不能再做这些准备工作了。
这里先不用清楚编解码器是如何工作的,这个是后面重点说明的内容,这里你只需要清楚,我们传输的以换行符为标识的数据,所以使用了Mina 自带的换行符编解码器工厂。
(3.) 第三步:编写IoHandler这里我们只是简单的打印Client 传说过来的数据。
public class MyIoHandler extends IoHandlerAdapter {
// 这里我们使用的SLF4J作为日志门面,至于为什么在后面说明。
private final static Logger log = LoggerFactory.getLogger(MyIoHandler.class);
@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
    String str = message.toString();
    log.info("The message received is [" + str + "]");
    if (str.endsWith("quit")) {
      session.close(true);
      return;
     }
   }
}
然后我们把这个IoHandler 注册到IoService:acceptor.setHandler(new MyIoHandler());当然这段代码也要在acceptor.bind()方法之前执行。
然后我们运行MyServer 中的main 方法,你可以看到控制台一直处于阻塞状态,此时,我们用telnet 127.0.0.1 9123 访问,然后输入一些内容,当按下回车键,你会发现数据在Server 端被输出,但要注意不要输入中文,因为Windows 的命令行窗口不会对传输的数据进行UTF-8 编码。当输入quit 结尾的字符串时,连接被断开。这里注意你如果使用的操作系统,或者使用的Telnet 软件的换行符是什么,如果不清楚,可以删掉第二步中的两个红色的参数,使用TextLineCodec 内部的自动识别机制。

2.简单的TCPClient:
这里我们实现Mina 中的TCPClient,因为前面说过无论是Server 端还是Client 端,在Mina中的执行流程都是一样的。唯一不同的就是IoService 的Client 端实现是IoConnector。
(1.) 第一步:编写IoService并注册过滤器
public class MyClient {
main方法:
    IoConnector connector=new NioSocketConnector();
    connector.setConnectTimeoutMillis(30000);
    connector.getFilterChain().addLast("codec",
    new ProtocolCodecFilter(
    new TextLineCodecFactory(
        Charset.forName("UTF-8"),
        LineDelimiter.WINDOWS.getValue(),
        LineDelimiter.WINDOWS.getValue()
       )
      )
    );
    connector.connect(new InetSocketAddress("localhost", 9123));
}
(2.) 第三步:编写IoHandler
public class ClientHandler extends IoHandlerAdapter {
    private final static Logger LOGGER = LoggerFactory.getLogger(ClientHandler.class);
    private final String values;
    public ClientHandler(String values) {
      this.values = values;
    }
    @Override
    public void sessionOpened(IoSession session) {
      session.write(values);
    }
}
注册IoHandler:
connector.setHandler(new ClientHandler("你好!\r\n 大家好!"));

然后我们运行MyClient,你会发现MyServer 输出如下语句:
 The message received is [你好!]
 The message received is [大家好!]

我们看到服务端是按照收到两条消息输出的,因为我们用的编解码器是以换行符判断数据是否读取完毕的。

总结:
  我们在这里已经简单的完成了使用mina进行网络通信,client和server之间传输一些数据,当然这是最基本的使用,后续我们会详细的介绍一些api以及更加具体复杂的案例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值