使用apache mina实现简单心跳服务

有些时候在开发cs应用的时候,服务端需要知道哪些在线和不在线,如果服务端用的是java框架,则可以使用此文章中的示例,这里只用到了mina的很基本的功能,没有使用到其他的高级的功能,主要是实现每多长时间检测一次是否接收到客户端的消息,以及客户端断开后的处理,实现类型在线状态的功能。

1、Server类

缓冲区默认是64字节,一般的服务只需要发送很短的消息,所以用默认的大小就可以了。

 

package com.qinyi.sitetv.main;

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

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.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

public class HearbeatServer {
	private static final int PORT = 9123;

	public static void main(String[] args) throws IOException {
		ResourceBundle bundle = ResourceBundle.getBundle("config");
		String idleTime = bundle.getString("idle_time");
		
		IoAcceptor acceptor = new NioSocketAcceptor();
		acceptor.getFilterChain().addLast("logger", new LoggingFilter());
        acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));
        acceptor.setHandler(new HearbeatHandler() );  
        //acceptor.getSessionConfig().setReadBufferSize( 2048 );
        acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, Integer.valueOf(idleTime) );
		acceptor.bind(new InetSocketAddress(PORT));
	}
}


2、消息处理类

 

 

 

package com.qinyi.sitetv.main;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;

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

import com.google.gson.Gson;
import com.qinyi.sitetv.main.service.HearbeatService;
import com.qinyi.sitetv.main.util.HttpClientUtil;

public class HearbeatHandler extends IoHandlerAdapter {
	
	private Logger log = Logger.getLogger(this.getClass());
	
	private ResourceBundle bundle = ResourceBundle.getBundle("config");
	
	private static final List<String> orgCodeList;
	private static Map<String, Long> org2sessionMap = new HashMap<String, Long>();
	private static Map<Long, String> session2orgMap = new HashMap<Long, String>();
	private static Map<Long, String> session2record = new HashMap<Long, String>();
	
	private HearbeatService hearbeatService = new HearbeatService();
	
	static {
		orgCodeList = new ArrayList<String>();
		initOrgCodeList();
	}
	
	@SuppressWarnings("unchecked")
	private static void initOrgCodeList() {
		String url = ResourceBundle.getBundle("config").getString("xxx");
		HttpClientUtil hc = new HttpClientUtil(url, null);
		String result = hc.get();
		Gson gson = new Gson();
		List<Map<String, String>> list = gson.fromJson(result, List.class);
		
		for (Map<String, String> map : list) {
			orgCodeList.add(map.get("org_code"));
		}
	}
	
	
	@Override
	public void sessionCreated(IoSession session) throws Exception {
		
		log.debug("session " + session.getId() + " is created, address: " + session.getRemoteAddress());
		
	}

	@Override
	public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
		cause.printStackTrace();
		log.error(cause.getMessage(), cause);
	}

	@Override
	public void messageReceived(IoSession session, Object message) throws Exception {
		String msg = message.toString();
		
		log.info(session.getId() + ", " + msg);
		
		if (!orgCodeList.contains(msg.trim()) || "quit".equals(msg)) {
			session.close(true);
			log.debug("session id " + session.getId() + ", msg is not available, will be close.");
			return;
		}

		if (!org2sessionMap.containsKey(msg)) {
			org2sessionMap.put(msg, session.getId());
			session2orgMap.put(session.getId(), msg);
			
			String recordId = hearbeatService.onlineStart(msg);
			if (recordId != null && !"".equals(recordId) ) {
				session2record.put(session.getId(), recordId);
				log.debug("sessionId: " + session.getId() + " =======> recordId: " + recordId);
			}
		}
	}

	@Override
	public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
		log.debug("session id: " + session.getId() + ", idle count: " + session.getIdleCount(status));
		
		int maxIdleCount = Integer.valueOf(bundle.getString("max_idle_count"));
		//如果超过最大次数没有接收到消息,则关闭连接
		if (session2orgMap.get(session.getId()) == null && session.getIdleCount(status) > maxIdleCount) {
			session.close(true);
			
			log.debug("session id " + session.getId() + ", no msg received, will be close.");
			return;
		}
		
		if (session.getIdleCount(status) > maxIdleCount) {
			onlineEnd(session);
			session.close(true);
			log.debug("session id " + session.getId() + ", no msg received, will be close.");
			return;
		}
	}

	@Override
	public void sessionClosed(IoSession session) throws Exception {
		log.debug("session " + session.getId() + " is closed");
		
		String orgCode = session2orgMap.get(session.getId());
		if (orgCode != null && !"".equals(orgCode)) {
			onlineEnd(session);
		}
	}

	private void onlineEnd(IoSession session) {
		String orgCode = session2orgMap.get(session.getId());
		String recordId = session2record.get(session.getId());
		
		session2orgMap.remove(session.getId());
		org2sessionMap.remove(orgCode);
		session2record.remove(session.getId());
		
		hearbeatService.onlineEnd(recordId);
	}
	
}


详细使用可参考:http://blog.youkuaiyun.com/defonds/article/details/17996123

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值