本文参考: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();
}
}
}
}