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所有,禁止任何形式的转载与引用。

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. 【Unity Shader实战】卡通风格的Shader(二)

    写在前面 本系列其他文章: 卡通风格的Shader(一) 好久没写博客了,一定是因为课程作业比较多,一定不是因为我懒,恩恩. 三个月以前,在一篇讲卡通风格的Shader的最后,我们说到在Surface ...

  2. 编译GDAL使用最新的HDF库配置文件

    HDF库最新版本中的动态库以及目录结构都发生了变化,导致按照之前的博客进行编译GDAL时,会出问题.使用HDF4版本为HDF4-4.2.10,HDF5的版本为HDF5-1.8.12.两个库的目录结构如 ...

  3. JavaScript中的三种弹出对话框

    学习过js的小伙伴会发现,我们在一些实例中用到了alert()方法.prompt()方法.prompt()方法,他们都是在屏幕上弹出一个对话框,并且在上面显示括号内的内容,使用这种方法使得页面的交互性 ...

  4. 【一天一道LeetCode】#111. Minimum Depth of Binary Tree

    一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given a ...

  5. visual studio 2015使用python tools远程调试maya 2016

    步骤: 1. 去https://apps.exchange.autodesk.com/MAYA/en/Home/Index搜索Developer Kit并下载,maya 2016可以直接点击这里下载. ...

  6. JavaScript 关键字

    JavaScript 关键字 和其他任何编程语言一样,JavaScript 保留了一些关键字为自己所用. JavaScript 同样保留了一些关键字,这些关键字在当前的语言版本中并没有使用,但在以后 ...

  7. pig的limit无效(返回所有记录)sample有效

    pig中,limit可以取样少部分数据,但有很多问题,比如数据不能少于10条,否则返回全部. 今天又遇到另一个问题: group后的数据,limit无效:也就是group后的数据,不能用limit,估 ...

  8. Leetcode_118_Pascal's Triangle

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/41827325 Given numRows, generat ...

  9. (NO.00001)iOS游戏SpeedBoy Lite成形记(二十七)

    切换回Xcode,在GameScene.m中添加新的实例变量:_winLayer. 接下来在第一个选手到达终点时,我们可以完成选手胜利的动画特效了. 首先,在GameScene.m中添加一个新方法pl ...

  10. 关于对数组和指针的测试与分析OC

    前言: 这个笔试题想必很多小伙伴都很面熟把,差不多10个人有7个人不会做这道笔试题,或许有知道答案的,但是仅仅知道答案,心里还是一头雾水.如果你真的不会那就请认真看完本文学习一下吧! 错误想法: 有的 ...