socket 客户端连接池实现

本文参考:http://cache.baidu.com/c?m=9f65cb4a8c8507ed4fece76310508a24420597634b86914323c3933fcf331d5c017be3b925251204d3c561640ab24859e1fa3c77341420c0c18ed714c9fecf6879877f67344f9141639244fe921163d620e14d99db0e96cce742e3b9a1d6c85523dd23016df1809c5b7003bb6ce76740f4d6ef5f635e07bb9d2715fe4e0123&p=8b2a9f1fce934eac59eace2c5f408c&newp=b46cc64adc9a02ff57ee9579420885231610db2151d0d74c3c&user=baidu&fm=sc&query=java+Socket+%BF%CD%BB%A7%B6%CB%C1%AC%BD%D3%B3%D8&qid=b594b3745708111f&p1=9

 

并对此文代码稍作修改,未经测试,只作参考。

 

自定义socket连接:

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

import org.apache.log4j.Logger;

/**
 * 

* Title: socket连接的简单实现 *

* *

* Description: *

* *

* Copyright: 融博技术有限公司 2012 *

* * @author 袁泉锋HO174959 * @version 1.0 * @date Oct 15, 2012 * */ public class SocketConnection extends Socket { private static final Logger logger = Logger.getLogger("FrameLog"); /** * status false 繁忙 true 空闲 */ private boolean status = true; /** * 默认的构造函数 */ public SocketConnection() { super(); } /** * ConnectionAdapter constructor */ public SocketConnection(String host, int port) throws UnknownHostException, IOException { super(host, port); } /** * 判断此连接是否空闲 * * @since Oct 15, 2012 * @return 空闲返回ture,否则false * */ public boolean isFree() { return status; } /** * 当使用此连接的时候设置状态为false(忙碌) * * @since Oct 15, 2012 * */ public void setBusy() { this.status = false; } /** * 当客户端关闭连接的时候状态设置为true(空闲),放回连接池 * * @since Oct 15, 2012 * */ public void close() { logger.info("ConnectionAdapter Close : set the status is free"); status = true; } /** * 销毁连接 * @throws IOException * * @since Oct 15, 2012 * */ public void destroy() throws IOException { //Close socket connection super.close(); logger.info("ConnectionAdapter destroy!"); // System.out.println( "Close success " ); } }

 

 

连接池接口:

 

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * 

* Title: 定义的抽象类,所有的子类必须单子模式去实现 *

* 统一方法为public ConnectionProvider newInstance(); * 连接提供器的抽象接口,每一个实现它的子类最好都是JAVABEAN, * 这样它的方法就可以是被外界控制 *

* Description: *

* *

* Copyright: 融博技术有限公司 2012 *

* * @author 袁泉锋HO174959 * @version 1.0 * @date Oct 15, 2012 * */ public interface SocketConnectionPoolInterface { public static final String SERVER_IP = "SERVER_IP_ADDRESS"; public static final String SERVER_PORT = "SERVER_IP_PORT"; public static final String MAX_SIZE = "MAX_SIZE"; public static final String MIN_SIZE = "MIN_SIZE"; /** *判断连接池内是否有连接 * @return true 有连接返回true,否则返回false */ public boolean isPooled(); /** * 当此方法被调用的时候提供一个 socket * @see Socket * @return Socket a Connection object. */ public SocketConnection getConnection() throws java.net.SocketException; /** * 连接池初始化 */ public void init() throws UnknownHostException, IOException; /** * 连接池重新启动 */ public void restart() throws UnknownHostException, IOException; /** * 注销连接池 */ public void destroy(); }

 

连接池接口实现:

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Properties;

import org.apache.log4j.Logger;


/**
 * 

* Title: 这是一个连接管理器的简单实现 *

* *

* Description: *

* *

* Copyright: 融博技术有限公司 2012 *

* * @author 袁泉锋HO174959 * @version 1.0 * @date Oct 15, 2012 * */ public class SocketConnectionPool implements SocketConnectionPoolInterface { private static final Logger logger = Logger.getLogger("FrameLog"); private Properties pro = null; private static SocketConnectionPoolInterface provider = null; private static Object object_lock = new Object(); private String ip; private String port; /** * 默认的最大连接数 */ private int max_size = 20; /** * 默认的最小连接数 */ private int min_size = 10; /** * Socket connection池数组 */ private SocketConnection[] socketpool = null; /** * 构造对象的时候初始化连接池 * @throws UnknownHostException 未知的主机异常 * @throws IOException */ private SocketConnectionPool(Properties pro) throws UnknownHostException, IOException { ip = pro.getProperty(SERVER_IP); port = pro.getProperty(SERVER_PORT); String max_size_s = pro.getProperty(MAX_SIZE); String min_size_s = pro.getProperty(MIN_SIZE); if (max_size_s != null) { max_size = Integer.parseInt(max_size_s); } if (min_size_s != null) { min_size = Integer.parseInt(min_size_s); } init(); //构造对象的时候初始化连接池 } /** * 判断是否已经池化 * @return boolean 如果池化返回ture,反之返回false */ public boolean isPooled() { if (socketpool != null) { return true; } else { return false; } } /** *返回一个连接 * @return a Connection object. */ public SocketConnection getConnection() { SocketConnection s = null; for (int i = 0; i < socketpool.length; i++) { if (socketpool[i] != null) { //如果有空闲的连接,返回一个空闲连接,如果没有,继续循环 if (socketpool[i].isFree()) { s = socketpool[i]; } else { continue; } } else { //如果连接为空,证明小于最小连接数,重新生成连接 try { s = socketpool[i] = new SocketConnection(ip, Integer .parseInt(port)); } catch (Exception e) { logger.error(e.getMessage()); //never throw } } } /*//TODO 如果连接仍旧为空的话,则超过了最大连接数 if (s == null) { try { //生成普通连接,由客户端自行关闭,释放资源,不再由连接池管理 s = new Socket(ip, Integer.parseInt(port)); } catch (Exception e) { //此异常永远不会抛出 } }*/ //TODO 如果连接仍旧为空的话,等待一会继续获取 while(s == null){ try { Thread.sleep(1000); s = this.getConnection(); } catch (InterruptedException e) { e.printStackTrace(); logger.error(e.getMessage()); } } s.setBusy(); return s; } /** * 初始化连接池 * @throws UnknownHostException 主机ip找不到 * @throws IOException 此端口号上无server监听 */ public void init() throws UnknownHostException, IOException { socketpool = new SocketConnection[max_size]; for (int i = 0; i < min_size; i++) { socketpool[i] = new SocketConnection(ip, Integer.parseInt(port)); logger.info(" . "); } logger.info("socketPool init success!"); } /** * 重新启动连接池 * @throws UnknownHostException * @throws IOException */ public void restart() throws UnknownHostException, IOException { destroy(); init(); } /** * 注销此连接池 */ public void destroy() { for (int i = 0; i < socketpool.length; i++) { if (socketpool[i] != null) { SocketConnection adapter = (SocketConnection) socketpool[i]; try { adapter.destroy(); } catch (IOException e) { logger.error(e.getMessage()); e.printStackTrace(); } logger.info(" . "); socketpool[i] = null; } } logger.info("SocketPool Destory success!"); } /** * 静态方法,生成此连接池实现的对象 * @param pro Properties 此连接池所需要的所有参数的封装 * @throws UnknownHostException 主机无法找到 * @throws IOException 与服务器无法建立连接 * @return ConnectionProvider 返回父类ConnectionProvider */ public static SocketConnectionPoolInterface newInstance(java.util.Properties pro) throws UnknownHostException, IOException { if (provider == null) { synchronized (object_lock) { if (provider == null) { provider = new SocketConnectionPool(pro); } } } return provider; } /** *设置系统属性 通过封装系统properties对象来封装所需要的不同值 * SERVER_IP,SERVER_PORT,MAX_SIZE,MIN_SIZE等父类定义的不同的参数 * @param pro Properties 传进来的系统属性 */ public void setProperties(Properties pro) { this.pro = pro; } }

 

连接池管理器:

import java.lang.reflect.*;
import java.util.Properties;

import org.apache.log4j.Logger;

/**
 * 

* Title: 连接管理器 *

* *

* Description: *

* *

* Copyright: 融博技术有限公司 2012 *

* * @author 袁泉锋HO174959 * @version 1.0 * @date Oct 15, 2012 * */ public class SocketConnectionManager { private static final Logger logger = Logger.getLogger("FrameLog"); //测试程序默认的连接池实现类 public static final String PROVIDER_CLASS = "com.rb.socketpool.MyConnectionProvider"; //测试程序的默认ip public static final String HOST = "127.0.0.1"; //测试程序的默认端口号 public static final String PORT = "9880"; /** * 注册钩子程序的静态匿名块,jvm退出的前一刻,调用ShutdownThread线程 */ static { Runtime runtime = Runtime.getRuntime(); Class c = runtime.getClass(); try { Method m = c.getMethod("addShutdownHook", new Class[] { Thread.class }); m.invoke(runtime, new Object[] { new ShutdownThread() }); } catch (NoSuchMethodException e) { logger.error(e.getMessage()); e.fillInStackTrace(); } catch (Exception e) { logger.error(e.getMessage()); e.printStackTrace(); } } /** * 默认的构造函数 */ public SocketConnectionManager() { } /** * 得到并初始化一个连接池 * 连接池的实现类通过系统参数来传递进来,通过命令行-DConnectionProvider=YourImplClass * 如果没有指定的实现的话,则采用系统默认的实现类 * 通过命令行传入的参数列表如下 * 对方主机名-DHost=192.168.0.200 * 对方端口号 -DPort=9880 * 最小连接数 -DMax_size=10 * 最大连结数 -DMin_size=20 * 以上的值可以改变,但是参数不能改变, * 最大连结数和最小连接数可以省略,默认值分别为20和10 * * @since Oct 15, 2012 * @return * @throws Exception * */ public static SocketConnectionPoolInterface getConnectionProvider() throws Exception { String provider_class = System.getProperty("ConnectionProvider"); if (provider_class == null){ provider_class = PROVIDER_CLASS; } String host = System.getProperty("Host"); if (host == null){ host = HOST; } String port = System.getProperty("port"); if (port == null){ port = PORT; } String max_size = System.getProperty("Max_size"); String min_size = System.getProperty("Min_size"); Properties pro = new Properties(); pro.setProperty(SocketConnectionPoolInterface.SERVER_IP, host); pro.setProperty(SocketConnectionPoolInterface.SERVER_PORT, port); if (max_size != null) { pro.setProperty(SocketConnectionPoolInterface.MAX_SIZE, max_size); } if (min_size != null) { pro.setProperty(SocketConnectionPoolInterface.MIN_SIZE, min_size); } //通过反射得到实现类 logger.info("Provider_class:" + provider_class); Class provider_impl = Class.forName(provider_class); //由于是单子模式,采用静态方法回调 Method m = provider_impl.getMethod("newInstance", new Class[] { java.util.Properties.class }); SocketConnectionPoolInterface provider = null; try { provider = (SocketConnectionPoolInterface) m.invoke(provider_impl, new Object[] { pro }); } catch (Exception e) { logger.error(e.getMessage()); e.printStackTrace(); } return provider; } /** * *

一个钩子的线程: 在程序结束的时候调用注销连接池

*

Description:

*

Copyright: Copyright Tarena(c) 2005

*

Company: Tarena

* @author chengxing * @version 1.0 */ private static class ShutdownThread extends Thread { public void run() { try { SocketConnectionPoolInterface provider = SocketConnectionManager .getConnectionProvider(); if (provider != null) { provider.destroy(); } } catch (Exception e) { logger.error(e.getMessage()); e.printStackTrace(); } } } }

 

 

你可能感兴趣的:(core,java)