java socket客戶端連接池

最近因項目需要,需要使用socket長連接服務器,但是在網上查資料發現都是服務器的連接池,於是自己動手寫了個客戶端socket連接池,記之,僅供參考,裏面的意義變量請自行替換,廢話少說,上代碼。


1.   socet信息類

    

package cn.richinfo.cloudp.dm.common.util;

import java.net.Socket;

/**
 * @Crop 深圳市xxx科技有限公司
 * @author liuxingmi 
 * @QQ 63972012
 * @DateTime 2014-8-25 下午3:21:19 
 * @Desc 名字服務器連接信息
 */
public class SocketInfo {

	/**
	 * socket
	 */
	private Socket socket;
	/**
	 * 是否空閒 (是:true  否:false)
	 */
	private boolean isFree;
	/**
	 * socket id
	 */
	private Integer socketId;
	
	/**
	 * 是否爲可關閉鏈接 (是:true  否:false)
	 */
	private boolean isClosed;

	public Socket getSocket() {
		return socket;
	}

	public void setSocket(Socket socket) {
		this.socket = socket;
	}

	public boolean isFree() {
		return isFree;
	}

	public void setFree(boolean isFree) {
		this.isFree = isFree;
	}

	public Integer getSocketId() {
		return socketId;
	}

	public void setSocketId(Integer socketId) {
		this.socketId = socketId;
	}

	public boolean isClosed() {
		return isClosed;
	}

	public void setClosed(boolean isClosed) {
		this.isClosed = isClosed;
	}

}

2.  鏈接池工具

package cn.richinfo.cloudp.dm.common.util;

import java.io.IOException;
import java.net.Socket;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import cn.richinfo.cloudp.common.config.CloudpConfigUtil;
import cn.richinfo.cloudp.common.constant.ConfigConst;
import cn.richinfo.cloudp.common.log.DMLogger;

/**
 * @Crop 深圳市xxxx有限公司
 * @author liuxingmi
 * @QQ 63972012
 * @DateTime 2014-8-25 下午3:18:18 
 * @Desc 分佈式名字服務器socket鏈接池
 */
public class SocketPool {
	
	private static DMLogger logger = DMLogger.getInstance();//日誌類
	
	/**
	 * socketMap
	 */
	public static ConcurrentHashMap<Integer, SocketInfo> socketMap = new ConcurrentHashMap<Integer, SocketInfo>();
	
	private static SocketPool instance = new SocketPool();
	
	private SocketPool(){}
	
	public static SocketPool getInstance(){
		if(instance == null){
			synchronized (SocketPool.class) {
				if(instance == null){
					instance = new SocketPool();
				}
			}
		}
		return instance;
	}
	
	static {
		instance.initSocket(true);
	}
	
	/**
	 * @DateTime 2014-8-25 下午3:18:52
	 * @User liuxingmi  
	 * @Desc 初始化鏈接池
	 * @param isAllReInit  是否全部重新初始化
	 * @return void
	 */
	public  void initSocket(boolean isAllReInit){
		int defaultCount = Integer.parseInt(ConfigConst.SOCKET_DEFAULT_COUNT);
		logger.info("nameserver:initSocket", DMLogger.RESULT_OK, "開始初始化分佈式名字服務器連接數:" + defaultCount);
		for (int i = 0; i < defaultCount; i++) {					
			
			if(isAllReInit){
				socketMap.put(i, setSocketInfo( i, true, false));
			} else {
				if(socketMap.get(i) == null || socketMap.get(i).isClosed()){
					socketMap.put(i, setSocketInfo( i, true, false));
				}
			}	
		}
		
		logger.info("nameserver:initSocket", DMLogger.RESULT_OK, "完成初始化分佈式名字服務器連接數");
		new CheckSocketThread().start();
		
	}
	
	/**
	 * @DateTime 2014-8-26 上午10:06:13
	 * @User liuxingmi  
	 * @Desc 設置socketInfo值
	 * @param socket
	 * @param key
	 * @param isFree
	 * @param isClosed
	 * @return SocketInfo
	 */
	private static SocketInfo setSocketInfo(Integer key, boolean isFree, boolean isClosed){
		SocketInfo socketInfo = new SocketInfo();
		Socket socket = createSocket();
		socketInfo.setFree(isFree);
		socketInfo.setSocket(socket);
		socketInfo.setSocketId(key);
		socketInfo.setClosed(isClosed);		
		return socketInfo;
	}
	
	/**
	 * @DateTime 2014-8-25 下午3:19:06
	 * @User liuxingmi  
	 * @Desc 獲取名字服務器鏈接
	 * @return
	 * SocketInfo
	 */
	public  SocketInfo getSocketInfo(){
		
		SocketInfo socketInfo = null;
		
		if(socketMap.size() < Integer.parseInt(ConfigConst.SOCKET_DEFAULT_COUNT)){
			initSocket(false);
		}		
	
		if(socketMap.size() > 0){
			for (Map.Entry<Integer, SocketInfo> entry : socketMap.entrySet()) {
				socketInfo = entry.getValue();
				if(socketInfo.isFree() && ! socketInfo.getSocket().isClosed()){
					socketInfo.setFree(false);
					return socketInfo;
				}
			}
		} else {
			logger.info("nameserver:socketInfo", DMLogger.RESULT_FAIL, "名字服務器socket連接池數量爲零。");
			return null;
		} 
		
		logger.info("nameserver:socketInfo", DMLogger.RESULT_OK, "所有名字服務器socket鏈接都忙,創建臨時鏈接。");
				
		socketInfo = setSocketInfo(-1, true, true);
		logger.info("nameserver:socketInfo", DMLogger.RESULT_OK, "成功創建服務器socket臨時鏈接。");	
		return socketInfo;

	}
	
	/**
	 * 釋放socket
	 * @param socketId
	 */
	public static void distorySocket(Integer socketId){
		
		logger.debug("nameserver:distorySocket", DMLogger.RESULT_OK, "釋放名字服務器socket鏈接。");
		SocketInfo socketInfo = socketMap.get(socketId);
		socketInfo.setFree(true);
		
	}
	
	/**
	 * @DateTime 2014-8-25 下午3:19:42
	 * @User liuxingmi  
	 * @Desc 釋放socket
	 * @param socketInfo
	 * void
	 */
	public static void distorySocket(SocketInfo socketInfo){
	   
		if(socketInfo == null) return;
		
		if( ! socketInfo.isClosed()){
			logger.debug("nameserver:distorySocket", DMLogger.RESULT_OK, "鏈接池socket,釋放資源。");
			distorySocket(socketInfo.getSocketId());
			return;
		}
		
		logger.debug("nameserver:distorySocket", DMLogger.RESULT_OK, "可關閉臨時鏈接,關閉socket");
		try {
			if(socketInfo.getSocket() != null){
				socketInfo.getSocket().close();
			}
		} catch (IOException e) {
			logger.error("nameserver:distorySocket", DMLogger.RESULT_FAIL, "關閉名字服務器socket鏈接失敗", e);
		}
		socketInfo = null;
		
	}
	
	/**
	 * @DateTime 2014-8-25 下午3:19:51
	 * @User liuxingmi  
	 * @Desc 創建socket
	 * @return
	 * Socket
	 */
	public static Socket createSocket(){
		
		String nameServerip1 = CloudpConfigUtil.DM_CONFIG.getNameSerIP1();
		int namServerport1 = CloudpConfigUtil.DM_CONFIG.getNameSerPort1();
		String nameServerip2 =  CloudpConfigUtil.DM_CONFIG.getNameSerIP2();
		int namServerport2 = CloudpConfigUtil.DM_CONFIG.getNameSerPort2();
		Socket socket = null;
		
		
		try {// 嘗試通過ip1第一次建立連接
			socket = new Socket(nameServerip1, namServerport1);
			logger.info("nameserver:login", DMLogger.RESULT_OK, "nameServerip1:" + nameServerip1 + ", namServerport1:" + namServerport1);
		} catch (IOException e) {			
			logger.error("nameserver:login", DMLogger.RESULT_FAIL, "first link fail nameServerip1:" + nameServerip1 + ", namServerport1:" + namServerport1, e);
		  try {
			  // 如果第一次通過ip1建立連接失敗,則進行第二次連接
			  socket = new Socket(nameServerip2, namServerport2);
			  logger.info("nameserver:login", DMLogger.RESULT_OK, "nameServerip2:" + nameServerip2 + ", namServerport2:" + namServerport2);
		     } catch (IOException e1) {
		    	logger.error("nameserver:login", DMLogger.RESULT_FAIL, "second link fail nameServerip2:" + nameServerip2 + ", namServerport2:" + namServerport2, e);
		    	return null;
		     }
		}
		return socket;
	}
	
	class CheckSocketThread extends Thread{
		@Override
		public void run() {
			while (true) {
				logger.debug("nameserver:checkSocket", DMLogger.RESULT_OK, "開始檢測分佈式鏈接狀態。");
				if(socketMap.size() < Integer.parseInt(ConfigConst.SOCKET_DEFAULT_COUNT)){
				    logger.info("nameserver:checkSocket", DMLogger.RESULT_OK, "分佈式名字服務器socket鏈接小於默認鏈接數,增加socket鏈接。");
					initSocket(false);
				}
				
				for (Map.Entry<Integer, SocketInfo> entry : socketMap.entrySet() ) {
					SocketInfo socketInfo = entry.getValue();
					if(socketInfo.getSocket() == null || socketInfo.isClosed()){
						logger.error("nameserver:checkSocket", DMLogger.RESULT_FAIL, "第"+ entry.getKey()+"個socket鏈接已關閉,重新連接分佈式。",null);
						socketInfo.setSocket(createSocket());
					} else {
						if(socketInfo.isFree()){
							boolean flag = NameServerUtils.getInstance().checkHeartbeat(socketInfo);
							if( ! flag ){
								logger.error("nameserver:checkSocket", DMLogger.RESULT_FAIL, "第"+ entry.getKey()+"個socket鏈接失敗,重新連接分佈式。",null);
								socketInfo.setSocket(createSocket());
								continue;
							}
						}
						logger.debug("nameserver:checkSocket", DMLogger.RESULT_OK, "第"+ entry.getKey()+"個socket鏈接正常。");
					}
				}
				
				try {
					sleep(Long.valueOf(ConfigConst.SOCKET_CHECK_TIME));
				} catch (Exception e) {
				} 
			}
		}
	}
	
}


發佈了40 篇原創文章 · 獲贊 4 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章