mina传输实现数据推送

来源:互联网 发布:低头族事故案数据调查 编辑:程序博客网 时间:2024/06/08 05:32

网上找的一些资料,整理一下

加上自己的理解写的一个Demo

注意:需要的包有这些:

<!-- mina -->
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-integration-beans</artifactId>
<version>2.0.13</version>
</dependency>
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-core</artifactId>
<version>2.0.13</version>
<type>bundle</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-integration-spring</artifactId>
<version>1.1.7</version>
</dependency>



1.客户端

package com.single.mina.Demo;



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.serialization.ObjectSerializationCodecFactory;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;


import com.single.mina.Demo.Util.ClientConstantUtil;


public class MinaScoketClient{

private ClientConstantUtil constan;
public void StateCount(){
//建立对象传输工厂》可以传大数据量
ObjectSerializationCodecFactory factory = new ObjectSerializationCodecFactory();
factory.setDecoderMaxObjectSize(Integer.MAX_VALUE);   
        factory.setEncoderMaxObjectSize(Integer.MAX_VALUE); 
        
//创建一个套接字连接诶
IoConnector connector = new NioSocketConnector();
//设置超时时间
connector.setConnectTimeoutMillis(ClientConstantUtil.getTime());
//设置读缓冲,传输的内容必须小于此缓冲
        //connector.getSessionConfig().setReadBufferSize(2048*2048);
//添加内置日志
connector.getFilterChain().addLast("log", new LoggingFilter());
//设置编码过滤器 
connector.getFilterChain().addLast("codec",
                new ProtocolCodecFilter(
                new TextLineCodecFactory(Charset.forName("utf-8"))));

/* connector.getFilterChain().addLast("volume",new ProtocolCodecFilter(factory));*/

//设置适配器(监听)
connector.setHandler(new ClientHandle(){
/*
* (non-Javadoc)
* @see org.apache.mina.core.service.IoHandlerAdapter#sessionClosed(org.apache.mina.core.session.IoSession)
* 连接关闭时调用
*/
@Override
public void sessionClosed(IoSession session) throws Exception {
// TODO Auto-generated method stub
System.out.println("连接关闭时调用");
for(;;){
try {
Thread.sleep(10000); 
System.out.println("重连测试");
                   ConnectFuture future = connector.connect(new InetSocketAddress(ClientConstantUtil.getHost(),ClientConstantUtil.getProt()));  
                   future.awaitUninterruptibly();// 等待连接创建成功  
                   session = future.getSession();// 获取会话 
                   if(session.isConnected()){
                   System.out.println("断线重连成功");
                   break;
                   }
} catch (Exception e){
System.out.println("重连失败,10秒后重连");
}
}
//super.sessionClosed(session);
}
});
IoSession session;
boolean bool = true;
for(;;){
try {
if(bool==false){
Thread.sleep(10000); 
}
System.out.println("建立连接测试");
                ConnectFuture future = connector.connect(new InetSocketAddress(ClientConstantUtil.getHost(),ClientConstantUtil.getProt()));  
                future.awaitUninterruptibly();// 等待连接创建成功  
                session = future.getSession();// 获取会话 
                //判断是否连上
                if(session.isConnected()){
                constan =ClientConstantUtil.getLoadBalancer();
                constan.setSession(session);
                break;
                }
} catch (Exception e) {
bool = false;
System.out.println("连接失败,10秒后重连");
}
}
//等待session关闭
       /* session.getCloseFuture().awaitUninterruptibly();*/
        //释放connector
       /* connector.dispose();*/
}

}

2.客户端监听

package com.single.mina.Demo;


import java.nio.charset.Charset;


import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;


public class ClientHandle extends IoHandlerAdapter{


/*
* (non-Javadoc)
* @see org.apache.mina.core.service.IoHandlerAdapter#sessionCreated(org.apache.mina.core.session.IoSession)
* 创建连接时调用
*/
@Override
public void sessionCreated(IoSession session) throws Exception {
// TODO Auto-generated method stub
System.out.println("创建连接时调用");
super.sessionCreated(session);
}


/*
* (non-Javadoc)
* @see org.apache.mina.core.service.IoHandlerAdapter#sessionOpened(org.apache.mina.core.session.IoSession)
* 连接打开时调用
*/
@Override
public void sessionOpened(IoSession session) throws Exception {
// TODO Auto-generated method stub
System.out.println("连接打开时调用");
super.sessionOpened(session);
}



/*
* (non-Javadoc)
* @see org.apache.mina.core.service.IoHandlerAdapter#sessionIdle(org.apache.mina.core.session.IoSession, org.apache.mina.core.session.IdleStatus)
* 连接等待时调用
*/
@Override
public void sessionIdle(IoSession session, IdleStatus status)
throws Exception {
// TODO Auto-generated method stub
System.out.println("连接等待时调用");
super.sessionIdle(session, status);
}


/*
* (non-Javadoc)
* @see org.apache.mina.core.service.IoHandlerAdapter#exceptionCaught(org.apache.mina.core.session.IoSession, java.lang.Throwable)
* 连接报错时调用
*/
@Override
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
// TODO Auto-generated method stub
System.out.println("连接报错时调用");
super.exceptionCaught(session, cause);
}


/*
* (non-Javadoc)
* @see org.apache.mina.core.service.IoHandlerAdapter#messageReceived(org.apache.mina.core.session.IoSession, java.lang.Object)
* 接收数据时调用
*/
@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
// TODO Auto-generated method stub
   System.out.println("接收数据时调用");
   System.out.println("客户端接收到的消息是"+message.toString());
   Thread.sleep(2000);
   //接收心跳信息
   if(message.toString().equals("1X11")){
    session.write("1X12");
   }
super.messageReceived(session, message);
}


/*
* (non-Javadoc)
* @see org.apache.mina.core.service.IoHandlerAdapter#messageSent(org.apache.mina.core.session.IoSession, java.lang.Object)
*  //当消息调用IoSession.write,返回消息 
*/
@Override
public void messageSent(IoSession session, Object message) throws Exception {
// TODO Auto-generated method stub
System.out.println("发送数据时调用");
super.messageSent(session, message);
}
}

3.服务端

package com.single.mina.Demo;


import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;


import javaxintioa.KeepAlive;


import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.session.IdleStatus;
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.filter.keepalive.KeepAliveFilter;
import org.apache.mina.filter.keepalive.KeepAliveMessageFactory;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;


//不用xml配置文件时可以这样写
public class MinaScoketServer{

public void StarServer(){
//创建一个非阻塞通道
IoAcceptor acceptor=new NioSocketAcceptor();  
//设置读缓冲
acceptor.getSessionConfig().setReadBufferSize(2048); 
//读写通道在5秒内无任何操作进入空闲状态--因为心跳包中加了空闲,该段代码可能失效
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE,5);
//绑定监听
acceptor.setHandler(new ServerHandle());
//心跳包设置
KeepAliveMessageFactory keep = new MyKeepAliveMessageFactory();
//心跳包超时断开连接
MyKeepAliveRequestTimeoutHandlerImpl heartbeatImpt = new MyKeepAliveRequestTimeoutHandlerImpl();
//空闲执行心跳
KeepAliveFilter heartBeat = new KeepAliveFilter(keep,IdleStatus.BOTH_IDLE,heartbeatImpt);
        // 是否回发 
       //heartBeat.setForwardEvent(false);
        // 发送频率 
        heartBeat.setRequestInterval(15);
//设置编码Filter拦截器,读取
/*acceptor.getFilterChain().addLast("codec",  
new ProtocolCodecFilter(  
new TextLineCodecFactory(  
Charset.forName("UTF-8"),LineDelimiter.WINDOWS.getValue(),LineDelimiter. WINDOWS.getValue())  
)  
);*/
//设置自定义的Filter拦截器,读取
        acceptor.getFilterChain().addLast("codec",
                new ProtocolCodecFilter(
                new TextLineCodecFactory(Charset.forName("utf-8"))));
//绑定
acceptor.getFilterChain().addLast("heartBeat", heartBeat);

try {
//绑定套接字,绑定端口
acceptor.bind(new InetSocketAddress(81));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("服务端以启动");
/*new Thread(){
public void run(){
int i =0;
while(true){
System.out.println(i++);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();*/
}



}

4.服务端监听

package com.single.mina.Demo;


import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;


import net.sf.json.JSONObject;


import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
















import org.dom4j.Entity;


import com.single.mina.Demo.Util.ClientPacketMina;
import com.single.mina.Demo.Util.QueueUtil;
import com.single.mina.Demo.Util.QueuelistUtil;




public class ServerHandle  extends IoHandlerAdapter {


/*
* (non-Javadoc)
* @see org.apache.mina.core.service.IoHandlerAdapter#sessionCreated(org.apache.mina.core.session.IoSession)
* 创建连接时调用
*/
@Override
public void sessionCreated(IoSession session) throws Exception {
// TODO Auto-generated method stub
System.out.println("服务端创建连接时调用");
super.sessionCreated(session);
}


/*
* (non-Javadoc)
* @see org.apache.mina.core.service.IoHandlerAdapter#sessionOpened(org.apache.mina.core.session.IoSession)
* 连接打开时调用
*/
@Override
public void sessionOpened(IoSession session) throws Exception {
// TODO Auto-generated method stub
System.out.println("服务端连接打开时调用");
super.sessionOpened(session);
}



/*
* (non-Javadoc)
* @see org.apache.mina.core.service.IoHandlerAdapter#sessionIdle(org.apache.mina.core.session.IoSession, org.apache.mina.core.session.IdleStatus)
* 连接等待时调用
*/
@Override
public void sessionIdle(IoSession session, IdleStatus status)
throws Exception {
// TODO Auto-generated method stub
System.out.println("服务端连接等待时调用");
super.sessionIdle(session, status);
}


/*
* (non-Javadoc)
* @see org.apache.mina.core.service.IoHandlerAdapter#exceptionCaught(org.apache.mina.core.session.IoSession, java.lang.Throwable)
* 连接报错时调用
*/
@Override
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
// TODO Auto-generated method stub
System.out.println("服务端连接报错时调用+Session:"+session+"错误"+cause);
session.closeOnFlush();
super.exceptionCaught(session, cause);
}


/*
* (non-Javadoc)
* @see org.apache.mina.core.service.IoHandlerAdapter#messageReceived(org.apache.mina.core.session.IoSession, java.lang.Object)
* 接收数据时调用
*/
@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
System.out.println("接收数据时调用");
InetAddress IP = ((InetSocketAddress)session.getRemoteAddress()).getAddress();
System.out.println(IP);
if(message!=null&&session!=null){
JSONObject json = JSONObject.fromObject(message.toString());
ClientPacketMina jsondate = (ClientPacketMina)JSONObject.toBean(json,ClientPacketMina.class);
System.out.println(jsondate.getDateJson());
QueueUtil queue = new QueueUtil();
//保存所有Session
Hashtable<String,QueueUtil> quelist = QueuelistUtil.getqueue().getList();
boolean bool = true;
//迭代判断该Session是否保存。
Iterator<String> itr = quelist.keySet().iterator();  
   while (itr.hasNext()){  
           String str = (String)itr.next();
           if(jsondate.getClientId().equals(str)){
            bool =false;
            break;
           }
        System.err.println(str+" (while) "+quelist.get(str));  
    }
   //在队列中不存在,保存到队列中
if(bool){
queue.setClientId(jsondate.getClientId());
queue.setIP(jsondate.getDateJson());
//获取单例队列
QueuelistUtil.getqueue().getList().put(queue.getClientId(),queue);
}
}
//session.write("2222222");
super.messageReceived(session, message);
}


/*
* (non-Javadoc)
* @see org.apache.mina.core.service.IoHandlerAdapter#messageSent(org.apache.mina.core.session.IoSession, java.lang.Object)
* 发送数据时调用
*/
@Override
public void messageSent(IoSession session, Object message) throws Exception {
super.messageSent(session, message);
}
}

5.自己定义编码,当然也可以用mina自带的

package com.single.mina.Demo;


import java.nio.charset.Charset;


import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolEncoder;
import org.apache.mina.filter.codec.textline.LineDelimiter;
import org.apache.mina.filter.codec.textline.TextLineDecoder;
import org.apache.mina.filter.codec.textline.TextLineEncoder;


/*
 * 可以自己写编码
 */
public class MyCodeFactory implements ProtocolCodecFactory{

    private final TextLineEncoder encoder;
    private final TextLineDecoder decoder;
    public MyCodeFactory() {
        this(Charset.forName("UTF-8"));
    }
    public MyCodeFactory(Charset charset) {
        encoder = new TextLineEncoder(charset, LineDelimiter.UNIX);
        decoder = new TextLineDecoder(charset, LineDelimiter.AUTO);
    }
    
    
    public ProtocolDecoder getDecoder(IoSession arg0) throws Exception {
        // TODO Auto-generated method stub
        return decoder;
    }
    public ProtocolEncoder getEncoder(IoSession arg0) throws Exception {
        // TODO Auto-generated method stub
        return encoder;
    }
    public int getEncoderMaxLineLength() {
        return encoder.getMaxLineLength();
    }
    public void setEncoderMaxLineLength(int maxLineLength) {
        encoder.setMaxLineLength(maxLineLength);
    }
    public int getDecoderMaxLineLength() {
        return decoder.getMaxLineLength();
    }
    public void setDecoderMaxLineLength(int maxLineLength) {
        decoder.setMaxLineLength(maxLineLength);
    }
}

6.mina自带的心跳包

package com.single.mina.Demo;




import java.net.InetSocketAddress;




import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.keepalive.KeepAliveMessageFactory;






public class MyKeepAliveMessageFactory implements KeepAliveMessageFactory{
/** 心跳包内容 */  
    private static final String HEARTBEATREQUEST = "1X11";  
    private static final String HEARTBEATRESPONSE = "1X12";
   
    
     //这个接口是用来获取一个心跳请求包。
    public Object getRequest(IoSession session) {
    System.out.println("请求预设信息心跳请求: " + HEARTBEATREQUEST); 
         return HEARTBEATREQUEST;
    }
    
    //这个接口是用来获取一个心跳回复包。
    public Object getResponse(IoSession session, Object request) {
    
    System.out.println("响应预设信息心跳回复: " + HEARTBEATRESPONSE);  
        /** 返回预设语句 */  
        return HEARTBEATRESPONSE;
    }
    
    //这个接口就是用来判断接收到的消息是不是一个心跳请求包。
    public boolean isRequest(IoSession session, Object message) {
    /*System.out.println("请求心跳包信息: " + message);*/
    System.out.println("请求心跳包地址心跳请求:"+((InetSocketAddress)session.getRemoteAddress()).getAddress().getHostAddress());
         if(message.equals(HEARTBEATREQUEST))
        return true;  
         return false;  
    }
    
    //这个接口就是用来判断接收到的消息是不是一个心跳回复包。
    public boolean isResponse(IoSession session, Object message) {
    /*System.out.println("响应心跳包信息: " + message);*/
    System.out.println("请求心跳包地址回复:"+((InetSocketAddress)session.getRemoteAddress()).getAddress().getHostAddress());
        if(message.equals(HEARTBEATRESPONSE))  
          return true;
        return false;
    }
}

7.心跳超时

package com.single.mina.Demo;


import org.apache.mina.core.future.CloseFuture;
import org.apache.mina.core.future.IoFuture;
import org.apache.mina.core.future.IoFutureListener;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.keepalive.KeepAliveFilter;
import org.apache.mina.filter.keepalive.KeepAliveRequestTimeoutHandler;


public class MyKeepAliveRequestTimeoutHandlerImpl implements KeepAliveRequestTimeoutHandler  {


@Override
public void keepAliveRequestTimedOut(KeepAliveFilter filter,
IoSession session) throws Exception {
System.out.println("服务器端心跳包发送超时处理(即长时间没有发送(接受)心跳包)---关闭当前长连接");
        CloseFuture closeFuture = session.close(true);
        closeFuture.addListener(new IoFutureListener<IoFuture>() {
            public void operationComplete(IoFuture future) {
                if (future instanceof CloseFuture) {
                    ((CloseFuture) future).setClosed();
                    System.out.println("sessionClosed 关闭,连接断开-->"+ future.getSession().getId());
                }
            }
        });

}
}

8.启动服务端

package com.single.mina.Demo;


public class StarServer {
public static void main(String arg[]){
MinaScoketServer scoket = new MinaScoketServer();
scoket.StarServer();
}
}

9.启动客户端

package com.single.mina.Demo;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;


import net.sf.json.JSONObject;


import org.apache.mina.core.session.IoSession;
import org.junit.Test;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.single.mina.Demo.Util.ClientConstantUtil;
import com.single.mina.Demo.Util.ClientPacketMina;

public class StarMina{
/* public StarMina(){
new Thread(){
public void run(){
MinaScoketClient client = new MinaScoketClient();
client.StateCount();
}
}.start();
}*/
private static String msg = null;


public static void main(String atg[]){

createConnection();
}

//创建连接

public static void createConnection(){
new Thread(){
@Override
public void run() {
MinaScoketClient client = new MinaScoketClient();
client.StateCount();
try {
//3秒后传值》数据传输
Thread.sleep(3000);
dongtai();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}

//数据传输 
public static void transmitData(String datejson){
//对传输的数据封包
ClientPacketMina packet = new ClientPacketMina();
packet.setClientId("1");
packet.setDateJson(datejson);
packet.setIP("3");
//业务标识
packet.setBusinesslogo("");
//命令字
packet.setCommandword("");
//客户端得到唯一IOSession保存
IoSession session = ClientConstantUtil.getLoadBalancer().getSession();
//《!--实体转成json--》
ObjectMapper mapper = new ObjectMapper();
String aa ="";
try {
aa = mapper.writeValueAsString(packet);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
JSONObject json = JSONObject.fromObject(aa);
//《!--实体转成json--》
session.write(json);
}
//动态传输
public static void dongtai(){
while(true){
Scanner scann = new Scanner(System.in);
System.out.println("输入传的数据");
String a = scann.next();
transmitData(a);
}
 
}

//得到某个文本里的东西
/*public static String Fileout(){
File fiel = new File("D:/hello/hello.txt");
String ab ="";
try {
FileOutputStream out = new FileOutputStream(fiel);
for(int i = 0;i<100000;i++){
try {
out.write("你好".getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
FileInputStream input = new FileInputStream(fiel);
byte[] b = new byte[(int) fiel.length()];
int count =0;
int temp = 0;
while((temp=input.read())!=-1){
b[count++]=(byte)temp;
}
input.close();
ab = new String(b);
} catch (IOException e) {
e.printStackTrace();
}
return ab;
}*/
}

11.下面是实体工具包

11.1

package com.single.mina.Demo.Util;


import org.apache.mina.core.session.IoSession;


public class ClientConstantUtil {

private static ClientConstantUtil instance;  
//服务端IP
private final static String host = "127.0.0.1";
//端口
private final static Integer prot = 81;
//超时时间》》按毫秒计算
private final static Integer time = 20000;
    //保存ioSession
private IoSession session;



    //公有静态成员方法,返回唯一实例 (单例)
    public static ClientConstantUtil getLoadBalancer() {  
       if (instance == null) {  
           instance = new ClientConstantUtil();  
       }  
       return instance;  
   }  
public static Integer getTime() {
return time;
}


public static String getHost() {
return host;
}
public static Integer getProt() {
return prot;
}

public  IoSession getSession() {
return session;
}
public  void setSession(IoSession session) {
this.session = session;
}
}

11.2

package com.single.mina.Demo.Util;


import java.util.Map;


import org.apache.commons.collections.map.HashedMap;


public class ClientPacketMina{

//客户端标识
private String clientId;
//传数据
private String dateJson;
//ip地址
private String IP;
//命令字
private String Commandword;
//业务标识
private String Businesslogo;




public String getCommandword() {
return Commandword;
}


public void setCommandword(String commandword) {
Commandword = commandword;
}


public String getBusinesslogo() {
return Businesslogo;
}


public void setBusinesslogo(String businesslogo) {
Businesslogo = businesslogo;
}


public String getClientId() {
return clientId;
}


public void setClientId(String clientId) {
this.clientId = clientId;
}


public String getDateJson() {
return dateJson;
}


public void setDateJson(String dateJson) {
this.dateJson = dateJson;
}


public String getIP() {
return IP;
}


public void setIP(String iP) {
IP = iP;
}







}

11.3

package com.single.mina.Demo.Util;


import java.util.Hashtable;






public class QueuelistUtil {

//队列保存在Hashable,线程安全
private static Hashtable<String,QueueUtil> list = new Hashtable<String, QueueUtil>();
    //单例创建
private static QueuelistUtil queue = null;
public static Hashtable<String, QueueUtil> getList() {
return list;
}


public static void setList(Hashtable<String, QueueUtil> list) {
QueuelistUtil.list = list;
}

public static QueuelistUtil getqueue(){
if(queue==null){
queue = new QueuelistUtil();
}
return queue;
}












}

11.4

package com.single.mina.Demo.Util;


import org.apache.mina.core.session.IoSession;


public class QueueUtil {

public QueueUtil(){


//设置公共的session类
private IoSession session;

    private String clientId;

private String IP;


public String getClientId() {
return clientId;
}


public void setClientId(String clientId) {
this.clientId = clientId;
}


public String getIP() {
return IP;
}


public void setIP(String iP) {
IP = iP;
}
}

0 0