C/S程序
概述
TCP协议的C/S程序使用ServerSocket搭建服务器,Socket搭建客户端来连接服务器,连接之后,服务器会返回一个Socket对象。
相关知识点
1、IP地址是计算机在互联网中的唯一标识。
2、端口号的范围 0-65535 之间,端口号在使用时,应尽量避免0-1024之间的端口号,因为已经被一些知名的软件和windows操作系统所占用了。
ServerSocket类和Socket类
ServerSocket(int port) //(构造方法)传入一个端口号,创建一个服务器
Socket(String host, int port) //(构造方法)传入ip地址和端口号,创建客户端并连接服务器
Socket accept() //服务器接收客户端连接
InputStream getInputStream() //发送消息
OutputStream getOutputStream() //接收消息
基于Java的C/S程序——图书管理系统
基本原理
1、服务器将视图界面通过输出流传给客户端,客户端通过输入流接收视图界面并输出到控制台(注意:不管服务器还是客户端输出的数据必须被接收,否则无法继续输出数据)。
2、客户端将从控制台接收到的信息通过输出流传给服务器,在服务器中调用方法,完成数据的修改,再通过输出流传给客户端处理信息。
书本类
public class Book implements Comparable<Book>{
private String name;
private double price;
private Date time;
public Book() {
}
public Book(String name, double price, Date time) {
this.name = name;
this.price = price;
this.time = time;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
return Double.compare(book.price, price) == 0 &&
Objects.equals(name, book.name) &&
Objects.equals(time, book.time);
}
@Override
public int hashCode() {
return Objects.hash(name, price, time);
}
@Override
public String toString() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String date = sdf.format(time);
return "图书名称:" + name + ",价格:" + price + ",出版时间:" + date ;
}
@Override
public int compareTo(Book o) {
return this.name.compareTo(o.name);
}
}
调用方法类
public class Dao {
/**
* 图书新增
* @param b 用户输入的图书信息
* @return
*/
public TreeSet<Book> add(Book b,TreeSet<Book> ts){
//遍历集合,查看集合是否已经包含用户新增的书本
for(Book b1:ts){
if(b.equals(b1)){
return null;
}
}
//向集合中添加元素
ts.add(b);
return ts;
}
/**
* 删除图书
* @param name 用户输入的要删除的图书名称
* @return
*/
public TreeSet<Book> delete(String name,TreeSet<Book> ts){
Iterator<Book> it = ts.iterator();
//遍历集合,查看集合是否已经有用户查找的书本
while (it.hasNext()){
Book b =it.next();
//如果有,返回这本书
if(name.equals(b.getName())){
ts.remove(b);
return ts;
}
}
return null;
}
/**
* 查找图书
* @param name 用户输入的要查找的图书名称(可模糊查找)
* @return
*/
public TreeSet<Book> findByName1(String name,TreeSet<Book> ts){
Iterator<Book> it = ts.iterator();
TreeSet<Book> al = new TreeSet<>();
//遍历集合,查看集合是否有用户查找的书本,如果有,判断书本的名字是否含有用户输入的关键字
while (it.hasNext()){
Book b =it.next();
if(b.getName().contains(name)){
al.add(b);
}
}
if(al.size() != 0){
return al;
}else{
return null;
}
}
/**
* 查找图书
* @param name 用户输入的要查找的图书名称(准确查找)
* @return
*/
public Book findByName2(String name,TreeSet<Book> ts){
Iterator<Book> it = ts.iterator();
//遍历集合,查看集合是否有用户查找的书本
while (it.hasNext()){
Book b =it.next();
if(b.getName().contains(name)){
return b;
}
}
return null;
}
/**
* 修改图书信息
* @param oldB 用户输入的旧图书信息
* @param newB 用户输入的新图书信息
* @return
*/
public TreeSet<Book> change(Book oldB, Book newB,TreeSet<Book> ts){
//删除原来的书本信息
ts.remove(oldB);
//新增修改后的书本信息
ts.add(newB);
return ts;
}
/**
* 以书本价格从低到高顺序显示所有图书
*/
public TreeSet<Book> show1(TreeSet<Book> ts){
//带有比较器的TreeSet集合
TreeSet<Book> ts1 = new TreeSet<>(new Comparator<Book>() {
@Override
public int compare(Book o1, Book o2) {
if(o1.getPrice() >= o2.getPrice()){
return 1;
}else{
return -1;
}
}
});
if(ts != null){
for(Book b:ts){
ts1.add(b);
}
return ts1;
}else{
return null;
}
}
/**
* 以书本价格从高到低顺序显示所有图书
*/
public TreeSet<Book> show2(TreeSet<Book> ts){
TreeSet<Book> ts2 = new TreeSet<>(new Comparator<Book>() {
@Override
public int compare(Book o1, Book o2) {
if(o1.getPrice() <= o2.getPrice()){
return 1;
}else{
return -1;
}
}
});
if(ts != null){
for(Book b:ts){
ts2.add(b);
}
return ts2;
}else{
return null;
}
}
/**
* 以书本出版日期从早到晚顺序显示所有图书
*/
public TreeSet<Book> show3(TreeSet<Book> ts){
TreeSet<Book> ts3 = new TreeSet<>(new Comparator<Book>() {
@Override
public int compare(Book o1, Book o2) {
long a1 = o1.getTime().getTime();
long a2 = o2.getTime().getTime();
if (a1>=a2){
return 1;
}else{
return -1;
}
}
});
if(ts.size() != 0){
for(Book b:ts){
ts3.add(b);
}
return ts3;
}else{
return null;
}
}
}
服务器
public class Server {
public static void main(String[] args) throws Exception {
//搭建服务器,端口号22223
ServerSocket server = new ServerSocket(22223);
Dao d = new Dao();
TreeSet<Book> ts = new TreeSet<>();
while (true) {
//等待客户端连接
Socket socket = server.accept();
//每个客户端连接都是一个线程
new Thread() {
@Override
public void run() {
//向客户端发送数据的流
OutputStream os = null;
try {
os = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
//向客户端发送欢迎界面
PrintStream ps = new PrintStream(os);
ps.println("=============欢迎使用图书系统=============");
//从客户端接收数据的流
InputStream is = null;
try {
is = socket.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
BufferedReader br = new BufferedReader(new InputStreamReader(is));
try {
br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
w1:while (true){
//向客户端发送登录界面
ps.println("请输入用户名:");
String name = null;
try {
//接收客户端传回的账号信息
name = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
ps.println("请输入密码:");
String password = null;
try {
//接收客户端传回的密码信息
password = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
//如果账号和密码正确,则登录成功
if("admin".equals(name) && "123456".equals(password)){
ps.println("登录成功");
w2:while (true) {
//向客户端发送管理员菜单界面
ps.println("请选择功能(1-图书新增,2-图书删除,3-图书修改,4-图书查找,5-查看所有图书,6-退出登录):");
String num = null;
try {
num = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
switch (num){
//新增图书
case "1":
ps.println("请输入新增图书名称:");
String book = null;
try {
//读取客户端传入的书名信息
book = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
ps.println("请输入新增图书的价格:");
String s = null;
try {
s = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
Double price = Double.parseDouble(s);
ps.println("请输入新增图书的出版日期(yyyy-MM-dd):");
String s1 = null;
try {
s1 = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date time = new Date();
try {
time = sdf.parse(s1);
} catch (ParseException e) {
e.printStackTrace();
}
Book b = new Book(book,price,time);
//调用添加方法,将图书新增
TreeSet<Book> ts1 = d.add(b,ts);
//判断是否新增成功
if(ts1 != null){
ps.println("新增成功");
}else{
ps.println("该图书已存在于系统中");
}
break;
//删除图书
case "2":
ps.println("请输入要删除的图书名称:");
String book1 = null;
try {
book1 = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
//调用删除图书方法将图书从系统中删除
TreeSet<Book> ts2 = d.delete(book1,ts);
if(ts2 != null){
ps.println("删除成功");
}else{
ps.println("系统中没有这本书");
}
break;
//修改图书信息
case "3":
ps.println("请输入要修改信息的图书书名:");
String book2 = null;
try {
book2 = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
//调用查找方法,判断要修改信息的图书系统中有没有
Book a = d.findByName2(book2,ts);
ps.println(a);
//有
if(a != null){
ps.println("请输入新的图书名称:");
String book3 = null;
try {
book3 = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
ps.println("请输入新的图书价格:");
String s2 = null;
try {
s2 = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
Double price1 = Double.parseDouble(s2);
ps.println("请输入新增图书的出版日期(yyyy-MM-dd):");
String s3 = null;
try {
s3 = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
Date time1 = new Date();
try {
time1 = sdf1.parse(s3);
} catch (ParseException e) {
e.printStackTrace();
}
Book b1 = new Book(book3,price1,time1);
//调用方法将系统中旧书信息删除,新书信息新增
TreeSet<Book> ts3 = d.change(a,b1,ts);
ps.println("修改成功");
}else{
ps.println("该图书不存在于系统中");
}
break;
//通过关键词查找图书
case "4":
ps.println("请输入要查找图书书名(可根据关键查找):");
String book4 = null;
try {
book4 = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
//查看系统中是否有这本书
TreeSet<Book> ts4 = d.findByName1(book4,ts);
ps.println(ts4);
if(ts4 != null){
//向客户端输出所有相关书籍信息
ps.println(ts4);
}else{
ps.println("未找到相关书籍");
}
break;
//查看所有图书信息
case "5":
//向客户端发送查看方式
ps.println("请选择查看方式(1-按图书价格顺序,2-按图书价格倒序,3-按图书出版日期顺序,4-返回上级目录):");
String num1 = null;
try {
num1 = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
switch (num1){
//按图书价格顺序
case "1":
TreeSet<Book> ts5 = d.show1(ts);
//向客户端输出所有书籍信息
ps.println(ts5);
if(ts5 == null){
ps.println("当前系统中没有图书");
}else{
ps.println("==============图书信息==============");
}
break;
//按图书价格倒序
case "2":
TreeSet<Book> ts6 = d.show2(ts);
ps.println(ts6);
if(ts6 == null){
ps.println("当前系统中没有图书");
}else{
ps.println("==============图书信息==============");
}
break;
//按图书出版日期顺序
case "3":
TreeSet<Book> ts7 = d.show3(ts);
ps.println(ts7);
if(ts7 == null){
ps.println("当前系统中没有图书");
}else{
ps.println("==============图书信息==============");
}
break;
//返回上级目录
case "4":
break;
default:
ps.println("请输入正确的操作");
break;
}
break;
//退出登录
case "6":
break w2;
default:
ps.println("请输入正确的操作");
break;
}
}
}else{
ps.println("用户名或密码错误");
}
}
}
}.start();
}
}
}
客户端
public class Client {
public static void main(String[] args) throws IOException {
//连接服务器,端口22223
Socket client = new Socket("127.0.0.1",22223);
//从服务器接收数据的流
InputStream is = client.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//接收的欢迎界面
String welcome = br.readLine();
System.out.println(welcome);
//向服务器输入数据的流
OutputStream os = client.getOutputStream();
PrintStream ps = new PrintStream(os);
Scanner input = new Scanner(System.in);
ps.println();
w1:while (true) {
//接收的登录界面(账号)
System.out.print(br.readLine());
String name = input.nextLine();
//将用户输入的账号传回服务器
ps.println(name);
//密码界面
System.out.print(br.readLine());
String password = input.nextLine();
//将用户输入的密码传回服务器
ps.println(password);
String s = br.readLine();
System.out.println(s);
//登录成功
if(s.equals("登录成功")){
w2:while (true) {
//接收的管理员菜单界面
System.out.print(br.readLine());
//向服务器传回用户输入的指令
String num = input.nextLine();
ps.println(num);
switch (num){
//新增图书
case "1":
//接收的输入新增图书信息界面(书名)
System.out.print(br.readLine());
ps.println(input.nextLine());
//价格
System.out.print(br.readLine());
ps.println(input.nextLine());
//出版时间
System.out.print(br.readLine());
ps.println(input.nextLine());
//从服务器接收新增成功与否信息
System.out.println(br.readLine());
break;
//删除图书
case "2":
//接收的要删除图书的信息(书名)
System.out.print(br.readLine());
ps.println(input.nextLine());
//从服务器接收删除成功与否信息
System.out.println(br.readLine());
break;
//修改图书信息
case "3":
//判断要修改的图书是否存在界面(书名)
System.out.print(br.readLine());
ps.println(input.nextLine());
//存在
if(br.readLine() != null){
//接收的新图书信息登记界面
System.out.print(br.readLine());
ps.println(input.nextLine());
//价格
System.out.print(br.readLine());
ps.println(input.nextLine());
//出版时间
System.out.print(br.readLine());
ps.println(input.nextLine());
//从服务器传来的登记成功界面
System.out.println(br.readLine());
}else{//不存在
System.out.println(br.readLine());
}
break;
//查找图书
case "4":
//接收的通过关键词查找图书界面(书名)
System.out.print(br.readLine());
ps.println(input.nextLine());
//找到图书
if(br.readLine() != null){
//图书信息集合
String ts = br.readLine();
//将字符串转换成集合
String[] b = ts.split(",");
for(int i = 0;i<b.length;i++){
System.out.println(b[i]);
}
}else{//没有找到图书
System.out.println(br.readLine());
}
break;
//查看所有图书信息
case "5":
//接收的查询方式界面
System.out.print(br.readLine());
String num1 = input.nextLine();
ps.println(num1);
switch (num1){
//按价格顺序查看
case "1":
//从服务器接收的所有图书信息集合
String ts2 = br.readLine();
if(ts2 == null){
System.out.println(br.readLine());
}else{
System.out.println(br.readLine());
String[] a1 = ts2.split(",");
for(int i = 0;i<a1.length;i++){
System.out.println(a1[i]);
}
}
break;
//按价格倒序查看
case "2":
String ts3 = br.readLine();
if(ts3 == null){
System.out.println(br.readLine());
}else{
System.out.println(br.readLine());
String[] a2 = ts3.split(",");
for(int i = 0;i<a2.length;i++){
System.out.println(a2[i]);
}
}
break;
//按出版日期顺序查看
case "3":
String ts4 = br.readLine();
if(ts4 == null){
System.out.println(br.readLine());
}else{
System.out.println(br.readLine());
String[] a3 = ts4.split(",");
for(int i = 0;i<a3.length;i++){
System.out.println(a3[i]);
}
}
break;
//返回上一级菜单
case "4":
break;
//接收的用户输入的操作有误界面
default:
System.out.println(br.readLine());
break;
}
break;
//退出登录
case "6":
break w2;
//接收的用户输入的操作有误界面
default:
System.out.println(br.readLine());
break;
}
}
}
}
}
}