Mina基础(二):基础服务端、客户端搭建

Apache Mina是一个能够帮助用户开发高性能和高伸缩性网络应用程序的框架。它通过Java nio技术基于TCP/IP和UDP/IP协议提供了抽象的、事件驱动的、异步的API。当前发行的 MINA 版本支持基于 Java NIO 技术的 TCP/UDP应用程序开发、串口通讯程序(只在最新的预览版中提供),MINA 所支持的功能也在进一步的扩展中。

API文档:

http://tool.oschina.net/apidocs/apidoc?api=mina

基础知识:

  • J2SE 基础知识

  • TCP协议:三次握手,四次挥手以及滑动窗口协议

  • UDP协议:封装报文

目标:通过Mina写一个简单的入门服务端程序

基本知识点:   1、Mina的概述

                         2、准备jar文件

                         3、初步理解编码器、解码器

                         4、实例练习

通过Mina创建一个服务端程序,用于监听客户端连接,并接受客户端发送过来的数据,当数据时exit时,那么服务端关闭。客户端通过telnet来模拟。

所需jar包

或者使用log4j2,部分pom如下

        <!-- Mina核心 -->
        <!-- https://mvnrepository.com/artifact/org.apache.mina/mina-core -->
        <dependency>
            <groupId>org.apache.mina</groupId>
            <artifactId>mina-core</artifactId>
            <version>2.0.19</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>

        <!-- 日志处理 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>${log4j2.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>${log4j2.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>${log4j2.version}</version>
        </dependency>

编码/解码

        在应用程序中数据时Java对象或基本数据类型,而在网络传输中,为二进制传输,所以在传输前需要进行编码,传输后需要进行解码

服务端程序实例

  1. 创建一个非阻塞的server端的Socket

  2. 设置编码过滤器(使用Mina提供的文本换行符编解码器)

  3. 设置读取数据的缓冲区大小

  4. 设置读写通道无操作进入空闲状态的时间 10ms

  5. 绑定真正的逻辑处理

  6. 绑定端口

/*
    测试Mina的简单例子
 */
public class MinaServer {
    private final static Logger logger = LogManager.getLogger(MinaServer.class);
    // 绑定的端口
    private static final int MINA_PORT = 7080;

    public static void main(String[] args) {
        IoAcceptor acceptor;
        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.getFilterChain().addFirst("filter", new MyServerFilter());
            // 设置读取数据的缓冲区大小
            acceptor.getSessionConfig().setReadBufferSize(1024);
            // 设置读写通道无操作进入空闲状态的时间 10ms
            acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
            // 绑定真正的逻辑处理
            acceptor.setHandler(new MyHandler());
            // 绑定端口
            acceptor.bind(new InetSocketAddress(MINA_PORT));
            logger.info("Mina服务端启动成功,监听:" + MINA_PORT);
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("服务端启动出错-----" + e);
        }
    }
}

逻辑处理,继承IoHandlerAdapter

public class MyHandler extends IoHandlerAdapter {
    private static final Logger logger = LogManager.getLogger(MyHandler.class);

    public MyHandler() {
        super();
    }

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

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

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

    @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);
    }

    @Override
    public void messageReceived(IoSession session, Object message) throws Exception {
        logger.info("服务端接受到消息:" + message);
        // 如果接受到exit,则退出程序
        if (message.equals("exit")) {
            session.closeNow();
        }
        Date date = new Date();
        session.write(date);
    }

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

    @Override
    public void inputClosed(IoSession session) throws Exception {
        logger.info("输入关闭");
    }
}

启动后,使用cmd的telnet模拟客户端测试:

telnet 127.0.0.1 7080

测试界面打印出的消息:

客户端程序

  1. 创建一个非阻塞的客户端

  2. 设置超时时间

  3. 设置编码解码器

  4. 绑定逻辑处理类

  5. 创建连接

  6. 等待连接创建完成

  7. 获取连接session

  8. 发送数据

  9. 等待关闭连接

(与服务端代码相似,不同的是服务端创建的是NioSocketAcceptor,而客户端创建的是NioSocketConnector

/*
    Mina客户端
 */
public class MinaClient {

    // 定义IP地址
    private static final String MINA_HOST = "127.0.0.1";
    // 定义端口
    private static final int MINA_PORT = 7080;

    public static void main(String[] args) {
        IoSession ioSession;
        // 创建一个非阻塞的客户端
        IoConnector ioConnector = new NioSocketConnector();
        // 设置超时时间
        ioConnector.setConnectTimeoutMillis(30000);
        // 设置编码解码器
        ioConnector.getFilterChain().addLast("codec", new ProtocolCodecFilter(
                new TextLineCodecFactory(
                        Charset.forName("UTF-8"),
                        LineDelimiter.WINDOWS.getValue(),
                        LineDelimiter.WINDOWS.getValue()
                )
        ));
        // 添加自定义过滤器
        ioConnector.getFilterChain().addFirst("filter", new MyClientFilter());
        // 绑定逻辑处理类
        ioConnector.setHandler(new MyClientHandler());
        // 创建连接
        ConnectFuture future = ioConnector.connect(new InetSocketAddress(MINA_HOST, MINA_PORT));
        // 等待连接创建完成
        future.awaitUninterruptibly();
        // 获取连接session
        ioSession = future.getSession();
        // 发送数据
        ioSession.write("你好啊,Mina");
        // 等待关闭连接
        ioSession.getCloseFuture().awaitUninterruptibly();
        ioConnector.dispose();
    }
}

客户端逻辑处理,同样继承IoHandlerAdapter

public class MyClientHandler extends IoHandlerAdapter {

    private static final Logger logger = LogManager.getLogger(MyClientHandler.class);

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

    @Override
    public void messageReceived(IoSession session, Object message) throws Exception {
        logger.info("客户端接收到数据:" + message);
    }
}

启动之前的服务端和当前的客户端,两者进行了通信:

Mina基础服务端、客户端搭建完毕   。

猜你喜欢

转载自blog.csdn.net/x3499633/article/details/81118502