登录 之 服务端响应

NIO服务端实现

新年第一篇

前面讲到的关于通讯机制的实现是客户端,现在将服务端响应的部分实现予以展示

package com.net;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class NioServer {
	private ReadProperties rp = new ReadProperties();
	private final String IP = rp.getProperty("ip");
	private final int SERVERPORT = Integer.parseInt(rp
			.getProperty("socketport"));
	private final String ISACK = "ACK";
	private final String ISNAK = "NAK!";
	private final String SPLITSTR = rp.getProperty("split_string");
	
	private ConnectionPool connpool=null;
	private Connection conn=null;
	private PreparedStatement pstmt=null;
	private ResultSet rs = null;
	private Hashtable<String,Integer> htMap=new Hashtable<String,Integer>();
	
	// Selector selector;//选择器
	// SelectionKey key;//key。 一个key代表一个Selector 在NIO通道上的注册,类似主键;//
	// 取得这个Key后就可以对Selector在通道上进行操作
	private ByteBuffer echoBuffer = ByteBuffer.allocate(1024);	// 通道数据缓冲区

	public NioServer() {
		this.initHashTable();
	}
	
	private void initHashTable(){
		htMap.put("land", 1);
		htMap.put("register", 2);
	}
	
	public void BuildNioServer() throws IOException {
		// ///////////////////////////////////////////////////////
		// ///////先对服务端的ServerSocket进行注册,注册到Selector ////
		// ///////////////////////////////////////////////////////
		ServerSocketChannel ssc = ServerSocketChannel.open();	// 新建NIO通道
		ssc.configureBlocking(false);			// 使通道为非阻塞,false
		ServerSocket ss = ssc.socket();			// 创建基于NIO通道的socket连接
		
		ss.bind(new InetSocketAddress(IP, SERVERPORT));	// 新建socket通道的端口
		Selector selector = Selector.open();			// 获取一个选择器
		ssc.register(selector, SelectionKey.OP_ACCEPT);	// 将NIO通道绑定到选择器,当然绑定后分配的主键为skey
		
		// //////////////////////////////////////////////////////////////////
		// //// 接收客户端的连接Socket,并将此Socket也接连注册到Selector ////
		// /////////////////////////////////////////////////////////////////
		while (true) {
			int num = selector.selectNow(); // 获取通道内是否有选择器的关心事件
			if (num < 1) continue;
			Set<SelectionKey> selectedKeys = selector.selectedKeys();
			Iterator<SelectionKey> it = selectedKeys.iterator();// 获取通道内关心事件的集合
			
			while (it.hasNext()) { 	// 遍历每个事件
				try {
					SelectionKey key = (SelectionKey) it.next();
					// 有一个新联接接入事件,服务端事件
					if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {
						// 接收这个新连接
						ServerSocketChannel serverChanel = (ServerSocketChannel) key.channel();
						// 从serverSocketChannel中创建出与客户端的连接 socketChannel
						SocketChannel sc = serverChanel.accept();
						sc.configureBlocking(false); 
						// 把新连接注册到选择器
						sc.register(selector,SelectionKey.OP_READ);
						it.remove();
					} else { 
						// 读客户端数据的事件,此时有客户端发数据过来,客户端事件
						if ((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) {
							// 读取数据
							SocketChannel sc = (SocketChannel) key.channel();

							if (sc.read(echoBuffer) > 0) {
								echoBuffer.flip();
								//System.out.println("limit:" + echoBuffer.limit());
								byte[] content = new byte[echoBuffer.limit()];
								echoBuffer.get(content);
								String result = new String(content);
								doPost(result, sc);
							}
							echoBuffer.clear();
							it.remove();
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

	public void doPost(String str, SocketChannel sc) {
		int firstIndex = str.indexOf(SPLITSTR);
		int secondIndex = str.lastIndexOf(SPLITSTR);
		String result = "";
		if (firstIndex > 0) {
			String name = str.substring(0, firstIndex);
			String pswd = str.substring(firstIndex + SPLITSTR.length(),
					secondIndex);
			String respondStyle = str.substring(secondIndex + SPLITSTR.length());
			if (name.length() != 0 && pswd.length() != 0 && respondStyle.length() != 0) {
				switch (this.htMap.get(respondStyle)) {
				case 1: // response of land
					if (validateLogOn(name, pswd)) {
						try {
							result = ISACK + SPLITSTR
										+ this.getLogOnUserInfo().getString("SName");
						} catch (SQLException e) {
							e.printStackTrace();
						}
					} else
						result = ISNAK + SPLITSTR + "userName or passwd error";
					break;
				case 2: // response of register
					if (validateUserExist(name)){
						result = ISNAK + SPLITSTR + name + " has existed";
					}else {
						if (registerUserInfo(name, pswd)){
							result = ISACK + SPLITSTR + name;
						}else result = ISNAK + SPLITSTR + "regist " + name + " failed";
					}
					break;
				default:
					System.out.println("No response to [" + respondStyle + "].");
					System.exit(1);
					break;
				}
			} else {
				System.out.println("At least one value of [name,passwd,respondStyle] is null.");
				System.exit(1);
			}
		} else {
			System.out.println("Can not receive split string.");
			System.exit(1);
		}

		ByteBuffer bb = ByteBuffer.allocate(result.length() + 10);
		bb.put(result.getBytes());
		bb.flip();
		try {
			sc.write(bb);
		} catch (IOException e) {
			e.printStackTrace();
		}
		bb.clear();
	}
	
	private boolean validateLogOn(String name,String passwd){
		connpool=ConnectionPool.getInstance();
		conn=connpool.getConnection();
		try {
			pstmt = conn.prepareStatement("select * from Student where SAccounts = ? and SPasswd = ?;");
			pstmt.setString(1, name);
			pstmt.setString(2, passwd);
			rs = pstmt.executeQuery();
			if(rs.next()){
				return true;
			}else return false;
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			connpool.releaseConnection(conn);
		}
		return false;
	}
	
	private ResultSet getLogOnUserInfo(){
		return this.rs;
	}
	
	private boolean validateUserExist(String name){
		connpool=ConnectionPool.getInstance();
		conn=connpool.getConnection();
		try {
			pstmt = conn.prepareStatement("select * from Student where SAccounts = ?;");
			pstmt.setString(1, name);
			rs = pstmt.executeQuery();
			if(rs.next()){
				return true;
			}else return false;
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			connpool.releaseConnection(conn);
		}
		return false;
	}
	
	private boolean registerUserInfo(String name,String passwd){
		connpool=ConnectionPool.getInstance();
		conn=connpool.getConnection();
		try {
			pstmt = conn.prepareStatement("insert into Student(SID,SName,SAccounts,SPasswd) values(?,?,?,?);");
			pstmt.setString(1, "id_"+name);
			pstmt.setString(2, "test_"+name);
			pstmt.setString(3, name);
			pstmt.setString(4, passwd);
			int rows=pstmt.executeUpdate();
			if(rows != 0){
				return true;
			}else {				
				return false;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			connpool.releaseConnection(conn);
		}
		return false;
	}
	
	public static void main(String[] args) throws IOException {
		NioServer ns = new NioServer();
		ns.BuildNioServer();
	}

}


为了提高数据库的连接性能,所以采用了连接池的设计:

定义连接池接口:ConnectionPoolInterface.java

package com.net;

import java.sql.Connection;

public interface ConnectionPoolInterface {
	public Connection getConnection(); 
	public void releaseConnection(Connection con);
}

实现连接代理:ConnectionHandler.java

package com.net;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;

public class ConnectionHandler implements InvocationHandler {
	private Connection con;
	private ConnectionPool pool;

	public ConnectionHandler(ConnectionPool pool) {
		this.pool = pool;
	}

	public Connection bind(Connection con) {
		this.con = con;
		// Connection proxyCon = (Connection) Proxy.newProxyInstance(con
		// .getClass().getClassLoader(), con.getClass().getInterfaces(),
		// this);
		Connection proxyCon = (Connection) Proxy.newProxyInstance(
				Connection.class.getClassLoader(),
				new Class[] { Connection.class }, this);
		return proxyCon;
	}

	public Object invoke(Object arg0, Method arg1, Object[] arg2)
			throws Throwable {
		// TODO Auto-generated method stub
		Object obj = null;
		if ("close".equals(arg1.getName())) {
			pool.releaseConnection(con);
		} else {
			obj = arg1.invoke(con, arg2);
		}
		return obj;
	}
}

最后实现连接池:ConnectionPool.java

package com.net;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Vector;

public class ConnectionPool implements ConnectionPoolInterface {

	private ReadProperties rp = new ReadProperties();
	private static Vector<Connection> pool;
	private static int POOL_MAX_SIZE = 0;
	private static ConnectionPool conPool = null;
	private static String DRIVER_NAME = "";
	private static String URL_BASE = "";
	private static String DB_NAME = "";
	private static String SERVER_IP = "";
	private static int SERVER_PORT = 0;
	private static String DB_ADMIN_NAME = "";
	private static String DB_ADMIN_PASSWD = "";

	ConnectionPool() {
		POOL_MAX_SIZE = Integer.parseInt(rp.getProperty("pool_max_size"));
		DRIVER_NAME = rp.getProperty("driver_name");
		URL_BASE = rp.getProperty("url_base");
		DB_NAME = rp.getProperty("db_name");
		SERVER_IP = rp.getProperty("server_ip");
		SERVER_PORT = Integer.parseInt(rp.getProperty("server_port"));
		DB_ADMIN_NAME = rp.getProperty("db_admin_name");
		DB_ADMIN_PASSWD = rp.getProperty("db_admin_passwd");
	}

	public static ConnectionPool getInstance() {
		if (conPool == null)
			return new ConnectionPool();
		else
			return conPool;
	}

	public synchronized Connection getConnection() {
		Connection con = null;
		try {
			if (pool == null)
				pool = new Vector<Connection>();
			if (pool.isEmpty()) {
				con = ConnectionPool.createConnection();
			} else {
				int index = pool.size() - 1;
				con = pool.get(index);
				pool.remove(pool.get(index));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		ConnectionHandler ch = new ConnectionHandler(this);
		return ch.bind(con);
	}

	public synchronized void releaseConnection(Connection con) {
		if (pool.size() > POOL_MAX_SIZE) {
			try {
				if (con != null) {
					con.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		} else {
			pool.add(con);
		}
	}

	private static Connection createConnection() {
		Connection con = null;
		try {
			Class.forName(DRIVER_NAME);
			con = DriverManager.getConnection(URL_BASE + "//" + SERVER_IP + ":"
					+ SERVER_PORT + "/" + DB_NAME, DB_ADMIN_NAME, DB_ADMIN_PASSWD);
		} catch (ClassNotFoundException CNFex) {
			CNFex.printStackTrace();
		} catch (SQLException SQLex) {
			SQLex.printStackTrace();
		}
		return con;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值