心跳检测


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;

import cn.edu.zju.cst.mina.im.server.entity.User;
import cn.edu.zju.cst.mina.im.server.handler.ServerControler;

public class UserStateManage extends Thread {
	
	//在线用户状态列表
	static HashMap
  
  
   
    userStateList = new HashMap
   
   
    
    ();
	Object hashLock = new Object();
	
	//当前的连接数和工作线程数
	static int workThreadNum = 0;
	static int socketConnect = 0;
	
	private ServerSocket serverSocket;
	//服务器IP
	private String host = "10.82.81.79";
	
	//服务器端口
	private int stateReportPort = 60001;
	
	//设置心跳包的结束标记
	String endFlag = "";
	CharSequence csEndFlag = endFlag.subSequence(0, 10);
	
	//扫描间隔
	private int scanTime = 1800; 
	
	
	@Override
	public void run() {
		//绑定端口,并开始侦听用户的心跳包
		serverSocket = startListenUserReport(stateReportPort);
		if(serverSocket == null){
			System.out.println("【创建ServerSocket失败!】");
			return;
		}
		//启动扫描线程
		Thread scanThread = new Thread(new scan());
		scanThread.start();
		//等待用户心跳包请求
		while(true){
			Socket socket = null;
			try {
				socketConnect = socketConnect + 1;
				//接收客户端的连接
				socket = serverSocket.accept();   
				//为该连接创建一个工作线程
				Thread workThread = new Thread(new Handler(socket));
				//启动工作线程
				workThread.start();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 创建一个ServerSocket来侦听用户心跳包请求
	 * @param port 指定的服务器端的端口
	 * @return 返回ServerSocket
	 * @author dream
	*/
	public ServerSocket startListenUserReport(int port){
		try {
			ServerSocket serverSocket = new ServerSocket();
			if(!serverSocket.getReuseAddress()){
				serverSocket.setReuseAddress(true);
			}
			serverSocket.bind(new InetSocketAddress(host,port));
			System.out.println("【开始在"+serverSocket.getLocalSocketAddress()+"上侦听用户的心跳包请求!】");
			return serverSocket;
		} catch (IOException e) {
			System.out.println("【端口"+port+"已经被占用!】");
			if (serverSocket != null) {
				if (!serverSocket.isClosed()) {
					try {
						serverSocket.close();
					} catch (IOException e1) {
						e1.printStackTrace();
					}
				}
			}
		}
		return serverSocket;
	}
	
	
	//工作线程类
	class Handler implements Runnable{
		private Socket socket;
		UserState us = null;
		User newUser = null;
		private int userId;
		private int userState;
		/**
		 * 构造函数,从调用者那里取得socket
		 * @param socket 指定的socket
		 * @author dream
		*/
		public Handler(Socket socket){
			this.socket = socket;
		}
		
		/**
		 * 从指定的socket中得到输入流
		 * @param socket 指定的socket
		 * @return 返回BufferedReader
		 * @author dream
		 */
		private BufferedReader getReader(Socket socket){
			InputStream is = null;
			BufferedReader br = null;

			try {
				is = socket.getInputStream();
				br = new BufferedReader(new InputStreamReader(is));
			} catch (IOException e) {
				e.printStackTrace();
			}
			return br;
		}
		
 		public void run() {
			try{
				workThreadNum = workThreadNum +1;
				System.out.println("【第"+workThreadNum+"个的连接:"+socket.getInetAddress()+":"+socket.getPort()+"】");
				BufferedReader br = getReader(socket);
				String meg = null;
				StringBuffer report = new StringBuffer();
				while ((meg = br.readLine()) != null) {
					report.append(meg);
					if (meg.contains(csEndFlag)) {
						us = getReporterUserState(meg, socket);
						synchronized (hashLock) {
							userStateList.put(userId, us);
						}
					}
				}
			}catch(IOException e){
				System.out.println("【客户:"+newUser.getUser_id()+"已经断开连接!】");
				userStateList.remove( userId );
				announceStateChange( userId , -1);
			}finally{
				if(socket != null){
					try {
						//断开连接
						socket.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}
 		private UserState getReporterUserState(String meg , Socket socket){
 			UserState us = new UserState();
 			try {
				Document requestDoc = DocumentHelper.parseText(meg);
				newUser = ServerControler.parseXmlToUserState(requestDoc,socket);
				userId = newUser.getUser_id();
				userState = newUser.getUser_state();
				us.setFlag(2);
				us.setUser_state( userState );
				us.setUser_id( userId );
				us.setUser_ip(newUser.getUser_ip());
				us.setUser_port(newUser.getUser_port());
			} catch (DocumentException e) {
				System.out.println("【来自客户端的信息不是一个合法的心跳包协议】");
			}
			return us;
 		}
	}
	
	//扫描线程
	class scan implements Runnable{
		public void run() {
			while (true) {
				System.out.println("*******"+new Date()+":扫描线程开始扫描"+"*******");
				synchronized (hashLock) {
					if(!userStateList.isEmpty()){
						//遍历在线用户列表
						for (Map.Entry
    
    
     
      entry : userStateList.entrySet()) {
							int flag = entry.getValue().getFlag();
							if ( (flag - 1) < 0) {
								//在这里通知该用户的好友其状态发生改变
//								announceStateChange(entry.getKey() , 0);
							}else{
								entry.getValue().setFlag(flag - 1);
								userStateList.put(entry.getKey(), entry.getValue());
							}
							System.out.println(entry.getKey() + "-->" + entry.getValue().toString());
						}
					}else{
						System.out.println("现在还没有在线用户!"); 
					}
				}
				//实现定时扫描
				try {
					sleep(scanTime);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	private void announceStateChange(int userId , int state){
		System.out.println("通知其好友!");
	}
	
	/**
	 * 查询一个用户是否在线
	 * @param userId 指定要查询状态的用户的ID
	 * @return true 在线; false 不在线;
	 * @author dream
	*/
	public boolean isAlive(int userId){
		synchronized (hashLock) {
			return userStateList.containsKey(userId);
		}
	}
	
	/**
	 * 返回指定用户ID的状态
	 * @param userId 指定要查询状态的用户的ID
	 * @return >0 该用户在线;  -1 该用户离线
	 * @author dream
	*/
	public int getUserState(int userId){
		synchronized (hashLock) {
			if(userStateList.containsKey(userId)){
				return userStateList.get(userId).getUser_state();
			}else{
				return -1;
			}
		}
	}
	
	public Object getHashLock() {
		return hashLock;
	}

	public void setHashLock(Object hashLock) {
		this.hashLock = hashLock;
	}

	public String getHost() {
		return host;
	}

	public void setHost(String host) {
		this.host = host;
	}

	public int getStateReportPort() {
		return stateReportPort;
	}

	public void setStateReportPort(int stateReportPort) {
		this.stateReportPort = stateReportPort;
	}

	public String getEndFlag() {
		return endFlag;
	}

	public void setEndFlag(String endFlag) {
		this.endFlag = endFlag;
	}

	public int getScanTime() {
		return scanTime;
	}

	public void setScanTime(int scanTime) {
		this.scanTime = scanTime;
	}

	public static HashMap
     
     
      
       getUserStateList() {
		return userStateList;
	}

	public static int getWorkThreadNum() {
		return workThreadNum;
	}

	public static int getSocketConnect() {
		return socketConnect;
	}
	//测试本函数的main函数
	public static void main(String arg[]){
		UserStateManage usm = new UserStateManage();
		usm.start();
	}
}

     
     
    
    
   
   
  
  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值