【推荐】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
来源:oschina
链接:https://my.oschina.net/u/2963604/blog/3154804