Mina的入门

来源:互联网 发布:文虎考堂 数据库 编辑:程序博客网 时间:2024/06/13 08:48

       之前学习了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端的代码。

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中的缓冲区,通道和选择器都没有出现,他们在哪呢?

原创粉丝点击