Socket连接池设计

 

技术要点
·读取并解析xml配置文件
·单例模式的使用
·适配器模式的使用
·JAVA的socket编程
·JAVA的多线程
·连接池的设计

起因:由于我做的系统需要模拟短信发送功能,选定的是用socket通信来模拟。WEB部分发送短信时需要不断的建立socket连接,收发消息,断开连接

。这样耗费是很大的,因为可能同时很多用户发短信,并且没发一条都要重复一次上述过程。起先想到了用单例模式。建立一个连接后就不断开,只要

有请求来了就可以取得该连接进行发送。但是后来发现了一个问题,如果多用户同时请求连接是无法控制向连接写数据时的互斥。初步设想可以使用

JAVA的synchronized关键字来实现,但是如果系统只有一个连接的话,无疑会使系统效率减慢很多。于是才想起了设计一个连接池。虽然只模拟,并

且做的系统是个Demo。但是还是学技术为主,呵呵。

起先设计了一个SocketAdapter类对Socket类进行装饰,使建立的连接能符合我们需要的功能和属性,这里貌似是适配器模式。具体设计如下:

public class SocketAdapter extends Socket { private boolean _status; private int _index; private BufferedReader _in; private PrintWriter _out; public SocketAdapter(int index, String host, int port) throws UnknownHostException, IOException { super(host, port); this._index = index; this._status = false; _out = new PrintWriter(this.getOutputStream()); _in = new BufferedReader(new InputStreamReader(this.getInputStream())); } public String send(String message) throws IOException { _out.println(message); _out.flush(); return _in.readLine(); } //getter、setter省略 }

考虑到更强的灵活性,使新建Socket连接时不在代码中写死服务器IP和服务端口及连接池大小。我参考了虞文镇师兄的代码写了个解析XML文件的类来

解析XML文件,并将其设计为单例模式。我暂时没搞清楚这里的单例模式有什么好处。设计读取配置文件的类时遇到了路径不正确的问题,因为我的

tomcat路径下有tomcat 6.0中间包含了一个空格为转义为%20,后面找到的方法为:新建一个URI对象来获取。代码如下:
configfile = new URI(this.getClass().getClassLoader() .getResource("").getPath() + "xxx.xml").getPath();

然后建立一个连接池SocketPool类,用一个数组来保存初始化时建立的SocketAdapter连接对象,除了传入host和port属性之外,将所有新建的连接

的使用状态设置为false,然后将其index属性设置为其在数组中的下标。具体设计如下:
新建POOL_SIZE大小的连接池。
private static synchronized void init() { self = new SocketPool(); SocketAdapter socket; try { for (int i = 0; i < POOL_SIZE; i++) { socket = new SocketAdapter(i, HOST, PORT); self.socketPool[i] = socket; } } catch (Exception e) { System.out.println("连接池建立失败!"); throw new RuntimeException(e); } System.out.println("连接池建立成功."); }

如果连接池中没有了可用的连接,那么会新建一个连接来使用,并且将其下标设置为-1并且不将其放入连接池中。当连接使用完需要放回连接池时先判

断下标是否为-1.如果为-1则简单的关闭连接。否则将其放入数组中下标为该连接idnex属性的所存储的位置处。

从连接池中获取一个连接:
public static SocketAdapter getSocket() { if (self == null) init(); int i = 0; for (i = 0; i < POOL_SIZE; i++) { if (!self.socketPool[i].is_status()) { self.socketPool[i].set_status(true); break; } } if (i < POOL_SIZE) { System.out.println("连接池中的第" + i + "个连接"); return self.socketPool[i]; } else { System.out.println("新建一个临时连接,没有空闲的连接"); SocketAdapter socket = null; try { socket = new SocketAdapter(-1, HOST, PORT); } catch (Exception e) { e.printStackTrace(); } return socket; } }  

释放一个连接如下:
public static void releaseSocket(SocketAdapter socket) { if (self == null) init(); if (socket.get_index() < 0) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } else self.socketPool[socket.get_index()].set_status(false); }


然后是服务器端的设计,服务器端运行后将一直处于等待状态,如果等待成功则新建一个子线程来执行与客户端的通信,JAVA的多线程很简单这里就略

过了。

整体说来还是比较简单,但是由于本人比较菜,从昨天上午开始写,修修改改,今天下午才写好。以上代码和解释不保证正确性,请需要参考的人自己过滤一遍。

你可能感兴趣的:(项目笔记)