Mina的入门

版权声明:本文为博主原创文章,未经博主允许不得转载。 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中的缓冲区,通道和选择器都没有出现,他们在哪呢?

猜你喜欢

转载自blog.csdn.net/liuyanlinglanq/article/details/76404776