版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liuyanlinglanq/article/details/76404776
之前学习了io的基础概念,又熟悉了一下NIO,现在可以了解一下NIO框架Mina了。
上来先做个demo,先简单的了解下。
根据不同的项目,首先引入jar包mina-core,我的是maven项目
<!--https://mvnrepository.com/artifact/org.apache.mina/mina-core-->
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-core</artifactId>
<version>2.0.16</version>
</dependency>
然后写代码,先是服务端
package mina;
import org.apache.mina.core.service.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 java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
/**
* Created by liuyanling on 2017/7/9.
*/
public class MinaServer {
static int port = 7080;
static IoAcceptor acceptor = null;
public static void main(String[] args) {
acceptor = new NioSocketAcceptor();
acceptor.getFilterChain().addLast("codec",new ProtocolCodecFilter(
new TextLineCodecFactory(Charset.forName("utf-8"), LineDelimiter.MAC.getValue(),LineDelimiter.MAC.getValue())
));
//acceptor.getFilterChain().addFirst("filter",new MyServerFilter());
acceptor.getSessionConfig().setBothIdleTime(10);
acceptor.getSessionConfig().setReadBufferSize(1024);
acceptor.setHandler(new MyHandler());
try {
acceptor.bind(new InetSocketAddress(port));
System.out.println("服务端启动->"+port);
} catch (IOException e) {
e.printStackTrace();
}
}
}
作为服务器端,主要就是发布一下自己的服务,说我的服务绑定在7080端口上了。由于这种网络传输,数据在网络中是以二进制流的方式传输的,所以从本地到网上要编码,从网上到本地要解码。于是用了默认的utf-8字符集,用了TextLineCodecFactory,文本行编解码器,以及行分割方式用的是mac的方式进行编解码。然后还配置了空闲时间以及读的缓冲区大小1024,最后要处理的业务在MyHandler这个类中。最后的最后,就是我刚刚说的了,服务发布到端口上。
public TextLineCodecFactory(Charset charset, String encodingDelimiter, String decodingDelimiter) {
encoder = new TextLineEncoder(charset, encodingDelimiter);
decoder = new TextLineDecoder(charset, decodingDelimiter);
}
* <ul>
* <li><b>Unix/Linux</b> : LineDelimiter.UNIX ("\n")</li>
* <li><b>Windows</b> : LineDelimiter.WINDOWS ("\r\n")</li>
* <li><b>MAC</b> : LineDelimiter.MAC ("\r")</li>
* </ul>
其中一个说说明TextLineCodecFactory主要是干了什么,它里面是一个编码器和一个解码器。而不同操作系统的分割方式就是\n和\r这样的区别了。
MyHandler类
package mina;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import java.util.Date;
/**
* Created by liuyanling on 2017/7/9.
*/
public class MyHandler extends IoHandlerAdapter {
@Override
public void sessionCreated(IoSession session) throws Exception {
System.out.println("sessionCreated");
}
@Override
public void sessionOpened(IoSession session) throws Exception {
System.out.println("sessionOpened");
}
@Override
public void sessionClosed(IoSession session) throws Exception {
System.out.println("sessionClosed");
}
@Override
public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
System.out.println("sessionIdle");
}
@Override
public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
System.out.println("exceptionCaught");
}
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
//接收客户端的消息,并打印
String msg = (String)message;
System.out.println("messageReceived,服务端接受到客户端消息:"+msg);
//长连接
if(msg.trim().equals("exit")) {
session.closeNow();
}
//发送消息到客户端
Date now = new Date();
session.write(now);
}
@Override
public void messageSent(IoSession session, Object message) throws Exception {
System.out.println("messageSent");
//短连接
//session.closeNow();
}
}
这个业务处理类,主要干的是就是接收来自客户端的信息。继承了IoHandlerAdapter类,实现了几个方法,session的开启和关闭,以及异常,还有消息的发送与接收,这些都是打印了一个信息到控制台就完了。而发送消息则是先打印接收到的消息,然后通过session的write()发送了一个时间给客户端了。
其中长连接和短连接是这样的一对,若要测试长连接的效果,则不能在messageSent消息发送之后就立马用session.closeNow()来关闭对话。而是在消息接收的时候,根据指令,若输入的exit,则关闭对话。当然长连接那段不写,默认也是长连接,但是就没办法正常关闭。
然后启动CMD,用 cmd telent 127.0.0.1:7080 来模拟客户端。连接到服务端之后,10秒空闲就会打印sessionId,输入消息watchmen,服务端会收到消息,并显示,然后发送一个时间给客户端。知道输入exit,就退出。
然后用cmd作为客户端也不是个事啊,于是写一下client端的代码。
扫描二维码关注公众号,回复:
6098298 查看本文章
package mina;
import org.apache.mina.core.filterchain.IoFilter;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.session.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 java.net.InetSocketAddress;
import java.nio.charset.Charset;
/**
* Created by liuyanling on 2017/7/10.
*/
public class MinaClient {
static int port = 7080;
static String host = "127.0.0.1";
public static void main(String[] args) {
//连接器
IoConnector connector = new NioSocketConnector();
IoSession session ;
connector.setConnectTimeoutMillis(3000L);
connector.getFilterChain().addLast("codec",
new ProtocolCodecFilter(
new TextLineCodecFactory(
Charset.forName("utf-8"),
LineDelimiter.MAC.getValue(),
LineDelimiter.MAC.getValue())
)
);
//connector.getFilterChain().addFirst("filter",new MyClientFilter());
connector.setHandler(new MyClientHandler());
//连接到服务器上,等待服务器发送消息,并给服务器发送消息,打个招呼;
ConnectFuture future = connector.connect(new InetSocketAddress(host,port));
future.awaitUninterruptibly(); //等待连接
session = future.getSession();
session.write("hello 服务端");
//关闭future和连接器
session.getCloseFuture().awaitUninterruptibly();
connector.dispose();
}
}
可以看出来,服务端建立的是NioSocketAcceptor接受器,而客户端建立的是NioSocketConnector连接器。然后设置了一下超时连接时间,以及和服务端一模一样的编解码方式,之后就是设置了客户端自己的业务处理。之后连接到服务端提供服务的地址上(host+端口),等待连接到服务器,之后用session给服务器发了个初次见面用的hello,之后用session关闭连接以及设置连接器销毁。而客户端的业务处理是
package mina;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
/**
* Created by liuyanling on 2017/7/10.
*/
public class MyClientHandler extends IoHandlerAdapter {
@Override
public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
System.out.println("exceptionCaught"+cause.getMessage());
}
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
String msg = (String) message;
System.out.println("客户端接收到服务器信息:"+msg);
}
}
超级简单的,异常处理打印异常消息,以及接收消息,打印出来。效果
以上就是mina的入门,和之前的nio代码比较一下,少了一堆的状态的判断和注册的鬼,确实简单了很多。很多东西都封在了NioSocketAcceptor和NioSocketConnector中,NIO中的缓冲区,通道和选择器都没有出现,他们在哪呢?