MINA(2)------快速开发Demo

烈酒焚心 提交于 2020-01-08 14:21:08

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

基础掌握:MINA整体体系结构分析

一.telnet模拟客户端

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

1、准备jar包:

(1)手动引入:

(2)添加如下代码到pom.xml中<dependencies></dependencies>标签内:

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.6.6</version>
        </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>
2、服务端:MinaServer.java

package com.mina;
 
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.filter.codec.ProtocolCodecException;
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;
 
public class MinaServer {
    static int PORT = 7080;
    static IoAcceptor accept = null; // 提供服务端实现
 
    public static void main(String[] args) {
        try {
            accept = new NioSocketAcceptor();
            // 设置过滤器
            accept.getFilterChain().addLast(
                    "codec",
                    new ProtocolCodecFilter(new TextLineCodecFactory(Charset
                            .forName("UTF-8"),
                            LineDelimiter.WINDOWS.getValue(),
                            LineDelimiter.WINDOWS.getValue())));
 
            // 设置缓冲区
            accept.getSessionConfig().setReadBufferSize(1024);// 大小
            accept.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);// 时间10s
            accept.setHandler(new MyHandler());// 业务
            accept.bind(new InetSocketAddress(PORT));// 绑定端口并启动
            System.out.println("Server ->" + PORT);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
3、业务逻辑:MyHandler.java

package com.mina;
 
import java.util.Date;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
 
public class MyHandler extends IoHandlerAdapter{
 
    @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("服务端接收到数据:" + msg);
        Date date = new Date();
        session.write(date); // 用于写入数据并发送
    }
 
    @Override
    public void messageSent(IoSession session, Object message) throws Exception {
        System.out.println("messageSent:" + "发送数据"); 
    }
 
    @Override
    public void sessionClosed(IoSession session) throws Exception {
        System.out.println("sessionClosed:" + "session关闭");
    }
 
    @Override
    public void sessionCreated(IoSession session) throws Exception {
        System.out.println("sessionCreated:" + "创建Session");
    }
 
    @Override
    public void sessionIdle(IoSession session, IdleStatus status)
            throws Exception {
        System.out.println("sessionIdle:" + "处于多长时间是空闲状态"); 
    }
 
    @Override
    public void sessionOpened(IoSession session) throws Exception {
        System.out.println("sessionOpened:" + "打开Session用于读写数据"); 
    }
 
}
4、telnet客户端

1)启动服务MinaServer.java

2)连接服务端端口,使用doc命令进入telnet客户端

注意:如果不能出现Telnet客户端窗口,可以在控制面板  --> 程序和功能  --> 打开或关闭Windows功能

3)长时间不操作客户端发送请求,就会造成服务端处于空闲状态,10s刷新一次

4)客户端发送“hello”,服务端接收数据并发送进行业务处理的数据

5)当客户端发送指定“exit”请求时,服务端“close”连接

修改方法中的代码

    @Override
    public void messageReceived(IoSession session, Object message)
            throws Exception {
        String msg = (String)message;
        if(msg.equals("exit")){
            session.close();
        }
        System.out.println("服务端接收到数据:" + msg);
        Date date = new Date();
        session.write(date); // 用于写入数据并发送
    }
telnet客户端

MINA服务端

二.Mina客户端编写

package com.mina;
 
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
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.NioSocketAcceptor;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
 
/**
 * Mina客户端
 * @author lenovo
 *
 */
public class MinaClient {
    private static String host = "127.0.0.1";
    private static int port = 7080;
    public static void main(String[] args) {
        IoSession session = null;
        IoConnector connector = new NioSocketConnector();// 提供客户端实现
        connector.setConnectTimeout(3000);// 设置超时时间
        // 设置过滤器(编码和解码)
        connector.getFilterChain().addLast("coderc", new ProtocolCodecFilter(
                new TextLineCodecFactory(Charset.forName("UTF-8"),
                        LineDelimiter.WINDOWS.getValue(),
                        LineDelimiter.WINDOWS.getValue())));
        // 业务处理
        connector.setHandler(new MyClientHandler());
        // 设置session属性,获取服务端连接
        ConnectFuture future = connector.connect(new InetSocketAddress(host,port));
        future.awaitUninterruptibly();// 等待我们的连接
        session = future.getSession();
        session.write("你好!Hello");// 写入数据,发往服务端
        session.getCloseFuture().awaitUninterruptibly();// 等待关闭连接
        connector.dispose();// 释放资源
    }
}
验证结果:启动服务端和客户端

总结:1)NIO Socket  2)设置编码解码过滤器  3)设置一些session属性  4)绑定一个端口

三.实践项目中的Mina服务端与线程优化实现。

package com.avnc.gateway.facade.listener;
 
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.log4j.Logger;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoEventType;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.executor.ExecutorFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
 
import com.neusoft.avnc.gateway.facade.listener.codec.bizSystem.BusinessSystemCodecFactory;
import com.neusoft.avnc.gateway.facade.listener.msgHandler.terminal.MessageHandler;
 
/**
 * <br>Title:协议监听器
 */
public class ListenerImpl  {
    
    public static final Logger LOG = Logger.getLogger("system");
    
    public boolean start(int port){
        
        LOG.info("[##########业务服务器监听初始化中......##########]");
        //创建一个非阻塞的server端的Socket来接受请求,执行读写操作的线程数设置为CPU核心数量+1
        NioSocketAcceptor acceptor = new NioSocketAcceptor(Runtime.getRuntime().availableProcessors()*2);
        //设置编码解码器
        acceptor.getFilterChain().addLast("checkcode",
                new ProtocolCodecFilter(new BusinessSystemCodecFactory()));
        //设置Message received处理线程
        ExecutorService executor = Executors.newFixedThreadPool(50);
        acceptor.getFilterChain().addLast("executor",
                new ExecutorFilter(executor,IoEventType.MESSAGE_RECEIVED));
        //会话开启处理线程池 - 对应句柄中的sessionOpened
        acceptor.getFilterChain().addLast("SessionOpenedThreadPool", 
                new ExecutorFilter(Executors.newCachedThreadPool(),IoEventType.SESSION_OPENED));
        //会话建立时处理线程池
        acceptor.getFilterChain().addLast("SessionCreatedThreadPool", 
                new ExecutorFilter(Executors.newCachedThreadPool(),IoEventType.WRITE));
        //设置句柄,业务处理,接收Client发来的请求,并发送处理完的数据到客户端
        acceptor.setHandler(new MessageHandler());
        // 读取数据的缓冲区大小
        acceptor.getSessionConfig().setReadBufferSize(1024*150);
        acceptor.getSessionConfig().setSendBufferSize(1024*150);
        // 读写通道均在40 秒内无任何操作就进入空闲状态
        acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 60);
        acceptor.setReuseAddress(true);
        acceptor.setCloseOnDeactivation(false);
        try {
            acceptor.bind(new InetSocketAddress(port));
            LOG.info("[##########业务服务器监听已启动,ON PORT:"+port+"##########]");
            return acceptor.isActive();
        } catch (IOException e) {
            LOG.error("业务服务器监听程序启动失败");
            return false;
        }
    }

————————————————
版权声明:本文为CSDN博主「贪吃丶蛇」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wang_snake/article/details/79495855

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!