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代码如下:

  1. package util;
  2.  
  3. import java.io.*;
  4. import java.util.*;
  5.  
  6. public class MyUtil {
  7.  
  8. public static void print(String param) {
  9. System.out.print(param);
  10. }
  11.  
  12. public static void println(String param) {
  13. System.out.println(param);
  14. }
  15.  
  16. public static String readln() {
  17. return readln(System.in);
  18. }
  19.  
  20. public static void send(OutputStream os, String msg) {
  21. try {
  22. OutputStreamWriter osw = new OutputStreamWriter(os);
  23. PrintWriter pw = new PrintWriter(osw, true);
  24. pw.println(msg);
  25. } catch (Exception e) {
  26. e.printStackTrace();
  27. }
  28.  
  29. }
  30.  
  31. public static String receive(InputStream is) {
  32. return readln(is);
  33. }
  34.  
  35. public static String readln(InputStream is) {
  36. try {
  37. InputStreamReader isr = new InputStreamReader(is);
  38. BufferedReader br = new BufferedReader(isr);
  39. String line = br.readLine();
  40. return line;
  41. } catch (Exception e) {
  42. e.printStackTrace();
  43. return "";
  44. }
  45. }
  46.  
  47. public static String getFileContent(String fileName) {
  48. StringBuffer content = new StringBuffer();
  49. InputStream fis = null;
  50. InputStreamReader isr = null;
  51. BufferedReader br = null;
  52. try {
  53. fis = MyUtil.class.getResourceAsStream("/"+fileName);
  54. if (fis == null) {
  55. System.out.println("File not found:[" + fileName + "]");
  56. return content.toString();
  57. }
  58. isr = new InputStreamReader(fis, "UTF-8");
  59. br = new BufferedReader(isr);
  60. String line = null;
  61. while ((line = br.readLine()) != null) {
  62. content.append(line);
  63. content.append("\r\n");
  64. }
  65. } catch (Exception e) {
  66. e.printStackTrace();
  67. return "";
  68. } finally {
  69. try {
  70. if (br != null) {
  71. br.close();
  72. }
  73. if (isr != null) {
  74. isr.close();
  75. }
  76. if (fis != null) {
  77. fis.close();
  78. }
  79. } catch (Exception e) {
  80. e.printStackTrace();
  81. }
  82. }
  83. return content.toString();
  84. }
  85.  
  86. public static String getFileContentBySql(String command) {
  87. try {
  88. command = command.replaceAll(";", "");
  89. StringBuffer result = new StringBuffer(); // select username, password from person where username = 'aaa'
  90. int selectPos = command.indexOf("select");
  91. int fromPos = command.indexOf("from");
  92. int wherePos = command.indexOf("where");
  93. if (selectPos == -1 || fromPos == -1) {
  94. return "incorrect SQL.";
  95. }
  96. String columnStr = command.substring(selectPos + "select".length(), fromPos).trim();
  97. String tableStr;
  98. String whereStr;
  99. if (wherePos == -1) {
  100. tableStr = command.substring(fromPos + "from".length()).trim();
  101. whereStr = "";
  102. } else {
  103. tableStr = command.substring(fromPos + "from".length(), wherePos).trim();
  104. whereStr = command.substring(wherePos + "where".length()).trim();
  105. }
  106. List<String> fileHeader = getFileHeaderList(tableStr + ".db");
  107. if (fileHeader.size() == 0) {
  108. return result.toString();
  109. }
  110. List<Map<String, String>> fileContent = getFileContentList(tableStr + ".db");
  111. String[] columnArray = null; // print header
  112. if (columnStr.equals("*")) {
  113. columnArray = new String[fileHeader.size()];
  114. int i = 0;
  115. for (String column : fileHeader) {
  116. result.append(column);
  117. if (i != fileHeader.size() - 1) {
  118. result.append(",");
  119. }
  120. columnArray[i++] = column;
  121. }
  122. result.append("\r\n");
  123. } else { // check
  124. boolean checkSelect = true;
  125. columnArray = columnStr.split(",");
  126. for (int i = 0; i < columnArray.length; i++) {
  127. checkSelect = false;
  128. for (int j = 0; j < fileHeader.size(); j++) {
  129. if (columnArray[i].trim().equals(fileHeader.get(j))) {
  130. checkSelect = true;
  131. break;
  132. }
  133. }
  134. if (!checkSelect) {
  135. String falseColumn = columnArray[i].trim();
  136. result.append("Unknow column:" + falseColumn + "\r\n");
  137. break;
  138. }
  139. }
  140. if (!checkSelect) {
  141. return result.toString();
  142. } // print header
  143. for (int i = 0; i < columnArray.length; i++) {
  144. result.append(columnArray[i]);
  145. if (i != columnArray.length - 1) {
  146. result.append(",");
  147. } else {
  148. result.append("\r\n");
  149. }
  150. }
  151. } // print content
  152. if (!whereStr.equals("")) {
  153. String[] whereExp = whereStr.split("and"); // for each row check where condition
  154. for (Map<String, String> rowMap : fileContent) {
  155. boolean checkRow = true;
  156. for (int i = 0; i < whereExp.length; i++) {
  157. String key = whereExp[i].split("=")[0].trim();
  158. String value = whereExp[i].split("=")[1].trim();
  159. String fileContentValue = rowMap.get(key);
  160. if (!value.equals(fileContentValue)) {
  161. checkRow = false;
  162. }
  163. }
  164. if (checkRow) {
  165. for (int i = 0; i < columnArray.length; i++) {
  166. result.append(rowMap.get(columnArray[i]));
  167. if (i != columnArray.length - 1) {
  168. result.append(",");
  169. } else {
  170. result.append("\r\n");
  171. }
  172. }
  173. }
  174. }
  175. } else {
  176. for (Map<String, String> rowMap : fileContent) {
  177. for (int i = 0; i < columnArray.length; i++) {
  178. result.append(rowMap.get(columnArray[i]));
  179. if (i != columnArray.length - 1) {
  180. result.append(",");
  181. } else {
  182. result.append("\r\n");
  183. }
  184. }
  185. }
  186. }
  187. return result.toString();
  188. } catch (Exception e) {
  189. return "Incorrect SQL.";
  190. }
  191. }
  192.  
  193. private static List<String> getFileHeaderList(String fileName) {
  194. List<String> result = new ArrayList<String>();
  195. InputStream fis = null;
  196. InputStreamReader isr = null;
  197. BufferedReader br = null;
  198. try {
  199. fis = MyUtil.class.getResourceAsStream("/"+fileName);
  200. if (fis == null) {
  201. System.out.println("File not found:[" + fileName + "]");
  202. return result;
  203. }
  204. isr = new InputStreamReader(fis, "UTF-8");
  205. br = new BufferedReader(isr);
  206. String line = null;
  207. if ((line = br.readLine()) != null) {
  208. String[] rowInfo = line.split(",");
  209. for (int i = 0; i < rowInfo.length; i++) {
  210. result.add(rowInfo[i]);
  211. }
  212. }
  213. } catch (Exception e) {
  214. e.printStackTrace();
  215. return result;
  216. } finally {
  217. try {
  218. if (br != null) {
  219. br.close();
  220. }
  221. if (isr != null) {
  222. isr.close();
  223. }
  224. if (fis != null) {
  225. fis.close();
  226. }
  227. } catch (Exception e) {
  228. e.printStackTrace();
  229. }
  230. }
  231. return result;
  232. }
  233.  
  234. private static List<Map<String, String>> getFileContentList(String fileName) {
  235. List<Map<String, String>> result = new ArrayList<Map<String, String>>();
  236. InputStream fis = null;
  237. InputStreamReader isr = null;
  238. BufferedReader br = null;
  239. try {
  240. fis = MyUtil.class.getResourceAsStream("/"+fileName);
  241. if (fis == null) {
  242. System.out.println("File not found:[" + fileName + "]");
  243. return result;
  244. }
  245. isr = new InputStreamReader(fis, "UTF-8");
  246. br = new BufferedReader(isr);
  247. String[] headerInfo = null;
  248. String line = null;
  249. while ((line = br.readLine()) != null) {
  250. if (headerInfo == null) {
  251. headerInfo = line.split(",");
  252. } else {
  253. String[] rowInfo = line.split(",");
  254. if (rowInfo.length != headerInfo.length) {
  255. System.out.println("Parse file error:[" + fileName + "]" + line);
  256. return result;
  257. }
  258. Map<String, String> rowInfoMap = new HashMap<String, String>();
  259. for (int i = 0; i < rowInfo.length; i++) {
  260. rowInfoMap.put(headerInfo[i], rowInfo[i]);
  261. }
  262. result.add(rowInfoMap);
  263. }
  264. }
  265. } catch (Exception e) {
  266. e.printStackTrace();
  267. return result;
  268. } finally {
  269. try {
  270. if (br != null) {
  271. br.close();
  272. }
  273. if (isr != null) {
  274. isr.close();
  275. }
  276. if (fis != null) {
  277. fis.close();
  278. }
  279. } catch (Exception e) {
  280. e.printStackTrace();
  281. }
  282. }
  283. return result;
  284. }
  285.  
  286. }

MyUtil.java

版权声明:本教程版权归java123.vip所有,禁止任何形式的转载与引用。

Java不走弯路教程(4.Client-Server模式(1)-Server)的更多相关文章

  1. Java不走弯路教程(5.Client-Server模式(2)-Client)

    5.Client-Server模式(2)-Client 在上一章,我们完成一个简单的数据库服务器,并在客户端用telnet方式成功进行通信. 本章将用Java实现客户端程序,来代替telnet. 先看 ...

  2. Java不走弯路教程(1.环境搭建)

    1.环境搭建在开始写第一个Java程序之前,我们需要做一些简单的准备工作. 1.1 还记得DOS吗 我们可以通过图形界面来操作我们的电脑.但作为程序员,你首先需要学会用命令行的方式来操作电脑,因为不是 ...

  3. Java不走弯路教程(前言)

    本教程的程序基于Windows开发,所以你需要有一台安装Windows操作系统的电脑. 前言本教程将带你完成Java的初学和WEB框架的开发,学完本教程,你将完成对Java的入门并且对下一步不再迷茫. ...

  4. Java不走弯路教程(2.Hello,Java!)

    2.Hello,Java! 欢迎来到Java的世界,在上一章,我们已经完成了DOS的基本操作学习和Java的环境搭建,在本章中我们Java来完成一个简单的DOS程序. 2.1 Hello,Java! ...

  5. Java不走弯路教程(3.用户验证与文件内容查询)

    3.用户验证与文件内容查询 在上一章中,我们完成了对指定文件内容的输出操作. 我们现在有如下格式的文件product.db id,product_name,product_detail 1,noteb ...

  6. Java不走弯路教程(6.JDBC)

    6.JDBC 在上一章,我们完成了MyDb数据库的简单的客户段调用.作为产品我们还封装了驱动程序,并且提供了统一的调用接口. 大家应该知道,市面上有多种数据库产品,比如Oracle,Mysql,DB2 ...

  7. JVM的Server与Client运行模式区别与切换

    概述 JVM有两种运行模式Server与Client.两种模式的区别在于,Client模式启动速度较快,Server模式启动较慢:但是启动进入稳定期长期运行之后Server模式的程序运行速度比Clie ...

  8. Java虚拟机6:内存溢出和内存泄露、并行和并发、Minor GC和Full GC、Client模式和Server模式的区别

    前言 之前的文章尤其是讲解GC的时候提到了很多的概念,比如内存溢出和内存泄露.并行与并发.Client模式和Server模式.Minor GC和Full GC,本文详细讲解下这些概念的区别. 内存溢出 ...

  9. java虚拟机--jvm client模式与server模式的区别

    JVM Server模式与client模式启动,最主要的差别在于:-Server模式启动时,速度较慢,但是一旦运行起来后,性能将会有很大的提升.JVM如果不显式指定是-Server模式还是-clien ...

随机推荐

  1. JAVA之旅(三十四)——自定义服务端,URLConnection,正则表达式特点,匹配,切割,替换,获取,网页爬虫

    JAVA之旅(三十四)--自定义服务端,URLConnection,正则表达式特点,匹配,切割,替换,获取,网页爬虫 我们接着来说网络编程,TCP 一.自定义服务端 我们直接写一个服务端,让本机去连接 ...

  2. SQL Server SA 最佳实践(也许不仅仅是翻译)

    老实说,本文主要部分是翻译的,并且由于英语水平的问题,我没有完全翻译,有些我觉得不重要的就跳过了,目前看来应该八九不离十,或者说不会影响最终效果,对于英语水平好的读者,可以自行查看原文.但这一年里面我 ...

  3. 文章标题 Oracle数据库中dual表使用

    一. 业务场景 业务流程需要进行写入和更新的比较,所以有原表和历史表. 要求表中的ID唯一性,以及两张表的ID关联,另外后续可能数据库会进行迁移 二.方案选择 方案一:id设置为int型自增长. 这种 ...

  4. Linux上程序调试的基石(2)--GDB

    3. GDB的实现 GDB是GNU发布的一个强大的程序调试工具,用以调试C/C++程序.可以使程序员在程序运行的时候观察程序在内存/寄存器中的使用情况.它的实现也是基于ptrace系统调用来完成的.  ...

  5. AsyncTask(异步任务)讲解-android的学习之旅(四十六)

    AsyncTask简介 Android的UI线程主要处理用户的按键,触屏和View的绘制等,不能在里面处理耗时的操作,否则会出现ANR,因此耗时的操作要单独开一个线程处理,但是新线程不能直接处理UI线 ...

  6. html5配合css3实现带提示文字的输入框(摆脱js)

    来源:互联网 作者:佚名 时间:03-08 11:41:53 [大 中 小] webkit特有的一个css,可以控制里面的文字样式,配合css3的动画效果和伪类,我们就可以很容易做出一个带动画的输入框 ...

  7. BottomSheet底部动作条使用

    底部动作条 底部动作条(Bottom Sheets)是一个从屏幕底部边缘向上滑出的一个面板,使用这种方式向用户呈现一组功能.底部动作条呈现了简单.清晰.无需额外解释的一组操作. 使用环境 底部动作条( ...

  8. listview优化(中)

    1,对Imageview使用setTag()方法来解决图片错位问题,这个Tag中设置的是图片的url,然后在加载的时候取得这个url和要加载那position中的url对比,如果不相同就加载,相同就是 ...

  9. Cygwin获取root权限

    .启动cygwin进入以后,就会以真正的root权限运行了.

  10. 【linux】mkfifo 命令创建命名管道实现进程之间通信

    mkfifo 命令 mkfifo命令创建一个FIFO特殊文件,是一个命名管道(可以用来做进程之间通信的桥梁) 管道也是一种文件,一般是linux中的一个页大小,4k,管道数据一旦被读取就没了.(管道大 ...