
4.Client-Server模式(1)-Server
在上一章中,我们完成了MyDataBase.java的编写,类似于一个简单的数据库功能,提供了用户验证,查询操作。
在本章中,我们将继续扩展这个程序。
数据库的数据一般存在于远程计算机(服务器)上,由多个客户进行连接,查询操作。
我们来模拟上述操作。
要访问某一台计算机上的某个程序,我们需要如下信息:
该机器的IP地址,程序所在的端口号
如下图所示:
所以,服务器端程序需要在某个端口监听客户断程序的连接,连接成功后,和客户端发送消息进行通信。
在Java中提供了java.net.ServerSocket和java.net.Socket类来分别实现服务端的监听和客户端的连接操作。
如下图所示:
我们写一个简单的服务器以便于理解:
编译运行。
我们用telnet来尝试连接该服务器。
DOS下输入如下命令:
telnet 127.0.0.1 8000
可以看到服务器的如下输出:
listening on port 8000
get a connection.
接下来要完成服务器和客户段的通信如下图所示:
这个通讯过程我们称为协议,即客户段和服务器段通信的规则。
因为这个规则是我们自己定义的,所以我们称他为自定义协议。
修改程序如下:
在程序的开始,我们创建了一个ServerSocket对象用如下语句:
ServerSocket ss = new ServerSocket(8000);
为什么需要创建对象?
对比如下两个类:
ServerSocket
MyUtil
我们在程序中可能创建多个ServerSocket,比如一个在8000端口监听,一个在9000端口监听,这样每个ServerSocket都有不同的端口,我们称之为有不同状态的类。
针对这种情况,我们在内存中分配不同的区域来表示不同端口号(状态)的ServerSocket。
在Java中,用new关键字来分配内存中的存储区域。
MyUtil类,在整个程序执行的过程中,并不存在不同的状态,所以无需重新分配存储区域。
现在,我们可以这样理解一个class文件:
第一行声明package信息。
然后生命需要引用的package信息。
然后生命class区块,用{}括起来。
class区块内,首先声明表示状态的变量,比如表示端口号的变量port。
接下来是多个方法区块,分别用{}括起来。
方法和class信息存在于方法区内。可以理解为类信息和一条一条的指令。
一旦用new关键字分配内存后,表示状态的变量将存在于堆内存中,可以理解为数据。
也就是,经过多次new的class,
方法和class信息只有一份,存在于方法区内,
表示状态的对象有多份,存在于堆内存中。
方法调用时,CPU从方法区中读取一条一条指令分别执行,如遇到数据引用,则从堆内存中读取该对象实际数据的值。
对于静态(static)方法/变量,由于只有一份,所以可以直接使用类名称来引用,
对于非静态(static)方法/变量,因为可能存在多份,所以必须由创建的对象来引用。
注:非静态方法也是有一份,但在CPU执行的时候方法中对变量的引用会绑定到堆内存中的不同的数据。
这也是静态方法不可以访问非静态方法/变量的原因,因为是一对多的关系,无法确定需要访问哪一个,
注:非静态方法也是有一份,但在CPU执行的时候方法中对变量的引用会绑定到堆内存中的不同的数据。
暂时这么理解,随着我们学习的深入,将会有更深入的理解方式。
输入输出流的概念我们在后续章节介绍,这里暂时跳过。
line.split(" ")是把line字符创的值按照空格分隔成数组,大家可以可以扩展学习字符串操作的其他方法,比如常用的indexOf,subString等。
注:字符串是实际开发中最常用的东西,对字符串的拼接,拆分,查找,替换操作要特别熟练。
main方法后面的 throws Exception 暂时忽略,我们在后续章节讲解。
编译运行。
我们用telnet来尝试连接该服务器。
DOS下输入如下命令:
telnet 127.0.0.1 8000
Input your name password:root abc
verify ok
select * from product
文件内容
exit
可以看到服务器的如下输出:
listening on port 8000
get a connection.
MyUtil.java代码如下:
package util; import java.io.*; import java.util.*; public class MyUtil { public static void print(String param) { System.out.print(param); } public static void println(String param) { System.out.println(param); } public static String readln() { return readln(System.in); } public static void send(OutputStream os, String msg) { try { OutputStreamWriter osw = new OutputStreamWriter(os); PrintWriter pw = new PrintWriter(osw, true); pw.println(msg); } catch (Exception e) { e.printStackTrace(); } } public static String receive(InputStream is) { return readln(is); } public static String readln(InputStream is) { try { InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String line = br.readLine(); return line; } catch (Exception e) { e.printStackTrace(); return ""; } } public static String getFileContent(String fileName) { StringBuffer content = new StringBuffer(); InputStream fis = null; InputStreamReader isr = null; BufferedReader br = null; try { fis = MyUtil.class.getResourceAsStream("/"+fileName); if (fis == null) { System.out.println("File not found:[" + fileName + "]"); return content.toString(); } isr = new InputStreamReader(fis, "UTF-8"); br = new BufferedReader(isr); String line = null; while ((line = br.readLine()) != null) { content.append(line); content.append("\r\n"); } } catch (Exception e) { e.printStackTrace(); return ""; } finally { try { if (br != null) { br.close(); } if (isr != null) { isr.close(); } if (fis != null) { fis.close(); } } catch (Exception e) { e.printStackTrace(); } } return content.toString(); } public static String getFileContentBySql(String command) { try { command = command.replaceAll(";", ""); StringBuffer result = new StringBuffer(); // select username, password from person where username = 'aaa' int selectPos = command.indexOf("select"); int fromPos = command.indexOf("from"); int wherePos = command.indexOf("where"); if (selectPos == -1 || fromPos == -1) { return "incorrect SQL."; } String columnStr = command.substring(selectPos + "select".length(), fromPos).trim(); String tableStr; String whereStr; if (wherePos == -1) { tableStr = command.substring(fromPos + "from".length()).trim(); whereStr = ""; } else { tableStr = command.substring(fromPos + "from".length(), wherePos).trim(); whereStr = command.substring(wherePos + "where".length()).trim(); } List<String> fileHeader = getFileHeaderList(tableStr + ".db"); if (fileHeader.size() == 0) { return result.toString(); } List<Map<String, String>> fileContent = getFileContentList(tableStr + ".db"); String[] columnArray = null; // print header if (columnStr.equals("*")) { columnArray = new String[fileHeader.size()]; int i = 0; for (String column : fileHeader) { result.append(column); if (i != fileHeader.size() - 1) { result.append(","); } columnArray[i++] = column; } result.append("\r\n"); } else { // check boolean checkSelect = true; columnArray = columnStr.split(","); for (int i = 0; i < columnArray.length; i++) { checkSelect = false; for (int j = 0; j < fileHeader.size(); j++) { if (columnArray[i].trim().equals(fileHeader.get(j))) { checkSelect = true; break; } } if (!checkSelect) { String falseColumn = columnArray[i].trim(); result.append("Unknow column:" + falseColumn + "\r\n"); break; } } if (!checkSelect) { return result.toString(); } // print header for (int i = 0; i < columnArray.length; i++) { result.append(columnArray[i]); if (i != columnArray.length - 1) { result.append(","); } else { result.append("\r\n"); } } } // print content if (!whereStr.equals("")) { String[] whereExp = whereStr.split("and"); // for each row check where condition for (Map<String, String> rowMap : fileContent) { boolean checkRow = true; for (int i = 0; i < whereExp.length; i++) { String key = whereExp[i].split("=")[0].trim(); String value = whereExp[i].split("=")[1].trim(); String fileContentValue = rowMap.get(key); if (!value.equals(fileContentValue)) { checkRow = false; } } if (checkRow) { for (int i = 0; i < columnArray.length; i++) { result.append(rowMap.get(columnArray[i])); if (i != columnArray.length - 1) { result.append(","); } else { result.append("\r\n"); } } } } } else { for (Map<String, String> rowMap : fileContent) { for (int i = 0; i < columnArray.length; i++) { result.append(rowMap.get(columnArray[i])); if (i != columnArray.length - 1) { result.append(","); } else { result.append("\r\n"); } } } } return result.toString(); } catch (Exception e) { return "Incorrect SQL."; } } private static List<String> getFileHeaderList(String fileName) { List<String> result = new ArrayList<String>(); InputStream fis = null; InputStreamReader isr = null; BufferedReader br = null; try { fis = MyUtil.class.getResourceAsStream("/"+fileName); if (fis == null) { System.out.println("File not found:[" + fileName + "]"); return result; } isr = new InputStreamReader(fis, "UTF-8"); br = new BufferedReader(isr); String line = null; if ((line = br.readLine()) != null) { String[] rowInfo = line.split(","); for (int i = 0; i < rowInfo.length; i++) { result.add(rowInfo[i]); } } } catch (Exception e) { e.printStackTrace(); return result; } finally { try { if (br != null) { br.close(); } if (isr != null) { isr.close(); } if (fis != null) { fis.close(); } } catch (Exception e) { e.printStackTrace(); } } return result; } private static List<Map<String, String>> getFileContentList(String fileName) { List<Map<String, String>> result = new ArrayList<Map<String, String>>(); InputStream fis = null; InputStreamReader isr = null; BufferedReader br = null; try { fis = MyUtil.class.getResourceAsStream("/"+fileName); if (fis == null) { System.out.println("File not found:[" + fileName + "]"); return result; } isr = new InputStreamReader(fis, "UTF-8"); br = new BufferedReader(isr); String[] headerInfo = null; String line = null; while ((line = br.readLine()) != null) { if (headerInfo == null) { headerInfo = line.split(","); } else { String[] rowInfo = line.split(","); if (rowInfo.length != headerInfo.length) { System.out.println("Parse file error:[" + fileName + "]" + line); return result; } Map<String, String> rowInfoMap = new HashMap<String, String>(); for (int i = 0; i < rowInfo.length; i++) { rowInfoMap.put(headerInfo[i], rowInfo[i]); } result.add(rowInfoMap); } } } catch (Exception e) { e.printStackTrace(); return result; } finally { try { if (br != null) { br.close(); } if (isr != null) { isr.close(); } if (fis != null) { fis.close(); } } catch (Exception e) { e.printStackTrace(); } } return result; } }
MyUtil.java
版权声明:本教程版权归java123.vip所有,禁止任何形式的转载与引用。