您的位置:首页 > 运维架构 > Apache

apache-Mina学习笔记

2017-06-07 19:43 423 查看
Apache Mina
      mina是apache基于socket nio的一套框架。支持基于socket
NIO库的TCP/UDP应用程序的开发。
看源码发现,它底层使用了线程池的技术。即Mina本身实现了线程池,为了提高效率,可以通过自己写连接池来使用Mina。这么理解,连接池中有多个IoSession,对于每一个IoSession,Mina不会为一个IoSession起一个线程,而是利用线程池来处理,这是NIO的好处。

Mina TCP的几个重要接口:
IoSession :是对底层连接的封装,对应于当前客户端到服务器端的一个TCP连接实例。连接池中保存着多个IoSession。
            这个接口有如下常用的方法:
                  WriteFuture write(Object message):通过这个方法发送数据。不会引起处理线程的阻塞。
IoHandler :这个接口负责编写业务逻辑,也就是接收、发送数据的地方。这也是实际开发过程中需要用户自己编写的部分代码。我们的项目中searchHub DataSource继承了该接口
            void
messageReceived(IoSession session, Object message) :
           
接收到消息时调用的方法,message 是一个IoBuffer 类,如果你使用了协议编解码器,那么可以强制转换为你需要的类型。

这里简单的介绍一下mina的框架:
IoService:这个接口是网络的入口,IoAcceptor和IoConnector都实现这个接口。
从名字上我们可以看得出来IoAcceptor是接受链接的(服务端),而IoConnector是用来链接的(客户端)。
IoConnector用于与服务端建立连接,每连接一个服务端就建立一个线程。
这两种线程都是通过线程池建立的。
这两个都是继承自IoService接口的抽象实现类AbstractIoService,在AbstractIoService源码中,有:



IoFilter:过滤器。他是用来过滤消息的。从IoService(网络接口)出来的数据或者进入IoService(网络接口)的数据都会经过IoFilter的处理。最重要的就是日志和解码和编码。
IoHandler:处理器。它是链接应用和IoFilter的桥梁,是进行业务处理的,从IoFilter出来的数据会发到IoHandler中处理。

通过例子进行学习:
目录结构:



1.服务端程序:(服务端绑定3005端口)

package com.dvn.li.main;

import java.net.InetSocketAddress;
import java.nio.charset.Charset;

import org.apache.log4j.Logger;
import org.apache.mina.common.IdleStatus;
import org.apache.mina.common.IoAcceptor;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.LineDelimiter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

import com.dvn.li.handler.Demo1ServerHandler;

public class Demo1Server {
private static Logger logger = Logger.getLogger(Demo1Server.class);

private static int PORT = 3005;

public static void main(String[] args) {
IoAcceptor acceptor = null; // 创建连接
try {
// 创建一个非阻塞的server端的Socket
acceptor = new NioSocketAcceptor();
// 设置过滤器(使用Mina提供的文本换行符编解码器)
acceptor.getFilterChain().addLast(
// 添加消息过滤器
"codec",
new ProtocolCodecFilter(new TextLineCodecFactory(Charset
.forName("UTF-8"),
LineDelimiter.WINDOWS.getValue(),
LineDelimiter.WINDOWS.getValue())));
// 设置读取数据的缓冲区大小
acceptor.getSessionConfig().setReadBufferSize(2048);
// 读写通道10秒内无操作进入空闲状态
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
// 绑定逻辑处理器
acceptor.setHandler(new Demo1ServerHandler()); // 添加业务处理
// 绑定端口
acceptor.bind(new InetSocketAddress(PORT));
logger.info("服务端启动成功...     端口号为:" + PORT);
} catch (Exception e) {
logger.error("服务端启动异常....", e);
e.printStackTrace();
}
}

}

服务器端的业务逻辑处理器是Demo1ServerHandler---看它的具体实现:

package com.dvn.li.handler;

import java.util.Date;

import org.apache.log4j.Logger;
import org.apache.mina.common.IdleStatus;
import org.apache.mina.common.IoHandlerAdapter;
import org.apache.mina.common.IoSession;

public class Demo1ServerHandler extends IoHandlerAdapter {
public static Logger logger = Logger.getLogger(Demo1ServerHandler.class);

@Override
public void sessionCreated(IoSession session) throws Exception {
logger.info("服务端与客户端创建连接...");
}

@Override
public void sessionOpened(IoSession session) throws Exception {
logger.info("服务端与客户端连接打开...");
}

@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
String msg = message.toString();
logger.info("服务端接收到的数据为:" + msg);
if ("bye".equals(msg)) { // 服务端断开连接的条件
session.close();
}
Date date = new Date();
String sendMess = "";
//逻辑处理
if(msg.contains("Hello")){
sendMess = "mina收到你的Hello!";
}else{
sendMess = "请跟mina say Hello!";
}
session.write(sendMess+" "+date); //往客户端发送消息
}

@Override
public void messageSent(IoSession session, Object message) throws Exception {
session.close();
logger.info("服务端发送信息成功...");
}

@Override
public void sessionClosed(IoSession session) throws Exception {

}

@Override
public void sessionIdle(IoSession session, IdleStatus status)
throws Exception {
logger.info("服务端进入空闲状态...");
}

@Override
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
logger.error("服务端发送异常...", cause);
}

}

2.客户端程序

package com.dvn.li.main;

import java.net.InetSocketAddress;
import java.nio.charset.Charset;

import org.apache.log4j.Logger;
import org.apache.mina.common.ConnectFuture;
import org.apache.mina.common.IoConnector;
import org.apache.mina.common.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.LineDelimiter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.nio.NioSocketConnector;

import com.dvn.li.handler.Demo1ClientHandler;

public class MinaClient01 {
private static Logger logger = Logger.getLogger(MinaClient01.class);

private static String HOST = "127.0.0.1";

private static int PORT = 3005;

public static void main(String[] args) {
// 创建一个非阻塞的客户端程序

a9dc
IoConnector connector = new NioSocketConnector();
// 设置链接超时时间
connector.setConnectTimeout(30000);
// 添加过滤器
connector.getFilterChain().addLast(
"codec",
new ProtocolCodecFilter(new TextLineCodecFactory(Charset
.forName("UTF-8"), LineDelimiter.WINDOWS.getValue(),
LineDelimiter.WINDOWS.getValue())));
// 添加业务逻辑处理器类
connector.setHandler(new Demo1ClientHandler());
IoSession session = null;
try {
ConnectFuture future = connector.connect(new InetSocketAddress(HOST, PORT));// 创建连接
future.awaitUninterruptibly();// 等待连接创建完成
session = future.getSession();// 获得session(可以结合连接池,从连接池获取一个session)
session.write("你好, mina");// 往服务端发送消息
} catch (Exception e) {
logger.error("客户端链接异常...", e);
}

session.getCloseFuture().awaitUninterruptibly();// 等待连接断开
connector.dispose();
}
}

        和服务端代码极其相似,不同的是服务端是创建NioSocketAcceptor对象,而客户端是创建NioSocketConnector对象;同样需要添加编码解码过滤器和业务逻辑过滤器;
业务逻辑过滤器代码:
package com.dvn.li.handler;

import org.apache.log4j.Logger;
import org.apache.mina.common.IoHandlerAdapter;
import org.apache.mina.common.IoSession;

public class Demo1ClientHandler extends IoHandlerAdapter {
private static Logger logger = Logger.getLogger(Demo1ClientHandler.class);

@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
String msg = message.toString();
logger.info("客户端接收到的信息为:" + msg);
}

@Override
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
logger.error("客户端发生异常...", cause);
}
}

3.执行过程:
    a.  启动服务端Demo1Server ,然后再启动客户端MinaClient01(客户端发送的消息是“Hello,mina”)
    b.  服务端接收消息并处理:如果客户端发送的消息包含hello,将 "mina收到你的Hello! "返回给客户端, 否则返回 "请跟mina say Hello!"
4.运行结果


















Demo参考地址:
http://blog.csdn.net/cgwcgw_/article/details/18402769
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: