NIO API是在Java 1.4引入的。MINA是基于NIO编写的。首先要了解NIO与BIO的概念以及区别,NIO代表非阻塞IO,BIO代表着阻塞式IO。
MINA是一个简单但功能齐全的网络应用框架(其实已经被NettyPK掉了,但都是一类型的东西,很多东西相通的,因为我们单位在用MINA所以优先看这个)。下载地址:http://mina.apache.org/downloads-mina.html 或者在maven中添加:
依赖
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.6</version>
<type>jar.sha256</type>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.6</version>
</dependency>
<dependency>
<groupId>org.rxtx</groupId>
<artifactId>rxtx</artifactId>
<version>2.1.7</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-core</artifactId>
<version>2.0.7</version>
</dependency>
</dependencies>
原理
编写自己的IoService,在这里我们创建IoService的子类。随后编写不同的过滤器(例如关于编解码的过滤器),将这些过滤器添加到过滤器链中,设置当前IoService监听的端口(可以是多个),设置处理器也就是业务逻辑编写的地方。
MINA说明:
当客户端向这一端口发送消息,IoService会监听这个端口,并经过过滤链进行处理后,传给IoHandler,在这个处理器中有很多函数,这些函数会在不同情况下触发(连接建立时、接收到消息时、连接关闭时、连接超时时等等)。你需要重写你需要的方法,在里面编写你的业务逻辑。
下面是MINA的一个示意图:
服务端
public class MinaServer {
public static void main(String[] args) throws IOException {
IoAcceptor acceptor = new NioSocketAcceptor();
acceptor.getFilterChain().addLast("logger", new LoggingFilter());
acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));
acceptor.setHandler(new TimeServerHandler());
acceptor.bind(new InetSocketAddress(9123));
}
}
public class TimeServerHandler extends IoHandlerAdapter {
private int count = 0;
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
String mes = message.toString();
if (mes.trim().equalsIgnoreCase("quit") || count > 2) {
System.out.println("退出服务器, count=" + count);
session.write("退出服务器, count=" + count);
session.close();
return;
}
session.write(count);
System.out.println("messageReceived: " + mes + ", count=" + count);
count++;
}
}
messageReceived方法接收消息,session.write回写消息
测试服务端
debug启动MinaServer
打开cmd窗口,输入命令Telnet localhost 9123
tcp客户端
客户端和服务器端的编写几乎是一样的,将IoService替换一下,服务器时我们用的是NioSocketAcceptor,客户端我们换成NioSocketConnector。这两个都是IoService的实现类。写法差不多直接上代码:
public class TcpClient {
public static void main(String[] args) {
NioSocketConnector connector = new NioSocketConnector();
connector.getFilterChain().addLast("logger", new LoggingFilter());
connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));
connector.setHandler(new TcpClientHanlder());
connector.connect(new InetSocketAddress("localhost", 9123));
}
}
public class TcpClientHanlder extends IoHandlerAdapter {
@Override
public void sessionCreated(IoSession session) throws Exception {
System.out.println("sessionCreated");
}
@Override
public void sessionOpened(IoSession session) throws Exception {
session.write("hello");
}
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
System.out.println("clientReceived: " + message.toString());
session.write("clientReceived: " + message.toString());
}
}
测试
先启动服务端,后启动客户端
服务端:
messageReceived: hello, count=0
messageReceived: clientReceived: 0, count=1
messageReceived: clientReceived: 1, count=2
退出服务器, count=3
客户端:
clientReceived: 0
clientReceived: 1
clientReceived: 2
clientReceived: 退出服务器, count=3
项目https://github.com/mingwulipo/mina-demo