20165326 java实验五
实验五 网络编程与安全
一、实验内容
任务一:
- 结对实现中缀表达式转后缀表达式的功能 MyBC.java
- 结对实现从上面功能中获取的表达式中实现后缀表达式求值的功能,调用MyDC.java
这个代码在之前四则运算的结对编程写过,基本上是一样的
代码:
MyBC的中缀转后缀的函数
public void conversion(String expr) { //中缀转后缀
String token;
StringTokenizer tokenizer = new StringTokenizer(expr);
while (tokenizer.hasMoreTokens()) {
//当tokenizer有下一个值时,进行循环,并把值赋给token
token = tokenizer.nextToken();
if (token.equals("(")) {
//如果是左括号,入栈
stack.push(token);
}else if (token.equals("+") || token.equals("-")) {
//如果是“+”或“-”,继续判断栈是否为空
if (!stack.empty()){
//如果栈非空,判断栈顶元素是什么
if (stack.peek().equals("(")) {
//如果栈顶为“(”,运算符入栈
stack.push(token);
}else{
//否则先把栈顶元素移除,加到列表中,再将运算符入栈
list.add(stack.pop());
stack.push(token);
}
}else {
//若栈为空,运算符入栈
stack.push(token);
}
}else if (token.equals("*") || token.equals("÷")){
//如果是“*”或“÷”,继续判断栈是否为空
if (!stack.empty()) {
//如果栈非空,判断栈顶元素是什么
if (stack.peek().equals("*") || stack.peek().equals("÷")) {
//如果栈顶为“*”或“÷”,先把栈顶元素移除,加到列表中,再将运算符入栈
list.add(stack.pop());
stack.push(token);
}else {
//如果栈顶为其他,运算符直接入栈
stack.push(token);
}
}else {
//如果栈为空,运算符直接入栈
stack.push(token);
}
} else if (token.equals(")")) {
//如果遇到“)”,开始循环
while (true) {
//先把栈顶元素移除并赋给A
String A = stack.pop();
if (!A.equals("(")) {
//如果A不为“(”,则加到列表
list.add(A);
} else {
//如果A为“(”,退出循环
break;
}
}
}else {
//如果为操作数,进入列表
list.add(token);
}
}
while (!stack.empty()) {
//将栈中元素取出,加到列表中,直到栈为空
list.add(stack.pop());
}
ListIterator<String> li = list.listIterator();//返回此列表元素的列表迭代器(按适当顺序)。
while (li.hasNext()) {
//将迭代器中的元素依次取出,并加上空格作为分隔符
Message += li.next() + " ";
li.remove();
}
message = Message;
}
public String getMessage() {
return message;
}
}
通过MyDCTester来进行测试检验
截图:
任务二:
结对编程:负责服务器
- 基于Java Socket实现客户端/服务器功能,传输方式用TCP
- 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式通过网络发送给服务器
- 服务器接收到后缀表达式,调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
- 客户端显示服务器发送过来的结果
我负责的是服务器,首先要知道我的IP地址,通过InetAddress
的静态变量getLocalHost()
进行获取
代码
import java.net.*;
public class Address {
public static void main(String[] args) throws UnknownHostException {
InetAddress net = InetAddress.getLocalHost();
System.out.println(net.toString());
}
}
截图:
服务器,先定义一个监听的端口号,再创建ServerSocket对象绑定监听端口,用accept方法与客户端创建连接,若连接异常则弹出错误。接着在利用DataInputStream获取客户端输入的数据和内容,并调用MyDC中的evaluate方法处理数据进行计算,接着利用DataOutputStream将数据返回给客户端,并打印出来结果,如有异常则弹出错误。等到socket为空时,关闭服务器结束。
服务器Sever2代码:
/*初始化socket和输入输出等*/
try {
System.out.println("等待客户呼叫");
socketOnServer = serverForClient.accept();
out = new DataOutputStream(socketOnServer.getOutputStream());
in = new DataInputStream(socketOnServer.getInputStream());
String s = in.readUTF();
System.out.println("服务器收到客户的提问:" + s);
MyDC myDC = new MyDC();
answer = myDC.evaluate(s);
out.writeUTF(answer + "");
Thread.sleep(500);
} catch (Exception e) {
System.out.println("客户已断开" + e);
}
}
}
截图:
任务三:
加密结对编程:负责服务器
- 把后缀表达式用3DES或AES算法加密后通过网络把密文发送给服务器
- 服务器接收到后缀表达式表达式后,进行解密(和客户端协商密钥,可以用数组保存),然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
- 其余与上任务同
实验步骤:首先运行Skey_DES.java
,将在当前目录下生成key1.data
保存产生的密钥。再运行Skey_kb.java
,在当前目录下生成keykb1.dat
保存上一步生成的密钥的编码。改写DES加密代码SEnc.java
,新添一个String类型成员变量,新添一个接受字符串参数的构造方法,并把其主函数改成加密方法,方便在客户端代码中直接调用。运行客户端代码Client.java
,在其中新建一个SEnc类实例,并调用该实例的加密方法,参数为后缀表达式;把密文文件和密钥编码文件发送给客户端,最后接收客户端返回的结果。
代码:
try {
System.out.println("等待客户呼叫");
socketOnServer = serverForClient.accept(); //堵塞状态,除非有客户呼叫
System.out.println("客户已连接");
out = new DataOutputStream(socketOnServer.getOutputStream());
in = new DataInputStream(socketOnServer.getInputStream());
String leng = in.readUTF(); // in读取信息,堵塞状态
byte ctext[] = new byte[Integer.parseInt(leng)];
for (int i = 0;i<Integer.parseInt(leng);i++) {
String temp = in.readUTF();
ctext[i] = Byte.parseByte(temp);
}
// 获取密钥
FileInputStream f2 = new FileInputStream("keykb1.dat");
int num2 = f2.available();
byte[] keykb = new byte[num2];
f2.read(keykb);
SecretKeySpec k = new SecretKeySpec(keykb, "DESede");
// 解密
Cipher cp = Cipher.getInstance("DESede");
cp.init(Cipher.DECRYPT_MODE, k);
byte[] ptext = cp.doFinal(ctext);
System.out.println("");
// 显示明文
String p = new String(ptext,"UTF8");
System.out.println("被解密的后缀表达式:" + p);
System.out.println("计算后缀表达式" + p);
out.writeUTF(mydc.evaluate(p)+"");
} catch (Exception e) {
System.out.println("客户已断开" + e);
}
}
}
截图:
任务四:
密钥分发结对编程:负责服务器
- 客户端和服务器用DH算法进行3DES或AES算法的密钥交换
- 服务器接收到后缀表达式表达式后,进行解密,然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
- 其余同上
甲为发送方,乙为接收方,甲乙双方构建密钥需要经过以下几个步骤:
- 由消息发送的一方构建密钥,这里由甲方构建密钥。
- 由构建密钥的一方向对方公布其公钥,这里由甲方向乙方发布公钥。
- 由消息接收的一方通过对方公钥构建自身密钥,这里由乙方使用甲方公钥构建乙方密钥。
- 由消息接收的一方向对方公布其公钥,这里由乙方向甲方公布公钥。
- 注意,乙方构建自己密钥对的时候需要使用甲方公钥作为参数这是很关键的一点
代码:
try {
System.out.println("等待客户呼叫");
socketOnServer = serverForClient.accept(); //堵塞状态,除非有客户呼叫
System.out.println("客户已连接");
out = new DataOutputStream(socketOnServer.getOutputStream());
in = new DataInputStream(socketOnServer.getInputStream());
Key_DH.DH("Spub.dat","Spri.dat");
int len = Integer.parseInt(in.readUTF());
byte np[] = new byte[len];
for (int i = 0;i<len;i++) {
String temp = in.readUTF();
np[i] = Byte.parseByte(temp);
}
ObjectInputStream ois = new ObjectInputStream (new ByteArrayInputStream (np));
Key k2 = (Key)ois.readObject();;
FileOutputStream f2 = new FileOutputStream("Cpub.dat");
ObjectOutputStream b2 = new ObjectOutputStream(f2);
b2.writeObject(k2);
FileInputStream fp = new FileInputStream("Spub.dat");
ObjectInputStream bp = new ObjectInputStream(fp);
Key kp = (Key) bp.readObject();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(kp);
byte[] kb = baos.toByteArray();
out.writeUTF(kb.length + "");
for (int i = 0; i < kb.length; i++) {
out.writeUTF(kb[i] + "");
}
KeyAgree.DH("Cpub.dat","Spri.dat");
String leng = in.readUTF(); // in读取信息,堵塞状态
byte ctext[] = new byte[Integer.parseInt(leng)];
for (int i = 0;i<Integer.parseInt(leng);i++) {
String temp = in.readUTF();
ctext[i] = Byte.parseByte(temp);
}
// 获取密钥
FileInputStream f = new FileInputStream("sb.dat");
byte[] keysb = new byte[24];
f.read(keysb);
System.out.println("公共密钥:");
for (int i = 0;i<24;i++) {
System.out.print(keysb[i]+",");
}
System.out.println("");
SecretKeySpec k = new SecretKeySpec(keysb, "DESede");
// 解密
Cipher cp = Cipher.getInstance("DESede");
cp.init(Cipher.DECRYPT_MODE, k);
byte[] ptext = cp.doFinal(ctext);
System.out.println("");
// 显示明文
String p = new String(ptext,"UTF8");
System.out.println("被解密的后缀表达式:" + p);
System.out.println("计算后缀表达式" + p);
out.writeUTF(mydc.evaluate(p)+"");
} catch (Exception e) {
System.out.println("客户已断开" + e);
}
}
}
截图:
任务五:
完整性校验结对编程:负责服务器
- 服务器接收到后缀表达式表达式后,进行解密,解密后计算明文的MD5值,和客户端传来的MD5进行比较,一致则调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
- 其余与上同
代码:
try {
System.out.println("等待客户呼叫");
socketOnServer = serverForClient.accept(); //堵塞状态,除非有客户呼叫
System.out.println("客户已连接");
out = new DataOutputStream(socketOnServer.getOutputStream());
in = new DataInputStream(socketOnServer.getInputStream());
Key_DH.DH("Spub.dat","Spri.dat");
int len = Integer.parseInt(in.readUTF());
byte np[] = new byte[len];
for (int i = 0;i<len;i++) {
String temp = in.readUTF();
np[i] = Byte.parseByte(temp);
}
ObjectInputStream ois = new ObjectInputStream (new ByteArrayInputStream(np));
Key k2 = (Key)ois.readObject();;
FileOutputStream f2 = new FileOutputStream("Cpub.dat");
ObjectOutputStream b2 = new ObjectOutputStream(f2);
b2.writeObject(k2);
FileInputStream fp = new FileInputStream("Spub.dat");
ObjectInputStream bp = new ObjectInputStream(fp);
Key kp = (Key) bp.readObject();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(kp);
byte[] kb = baos.toByteArray();
out.writeUTF(kb.length + "");
for (int i = 0; i < kb.length; i++) {
out.writeUTF(kb[i] + "");
}
KeyAgree.DH("Cpub.dat","Spri.dat");
String leng = in.readUTF(); // in读取信息,堵塞状态
byte ctext[] = new byte[Integer.parseInt(leng)];
for (int i = 0;i<Integer.parseInt(leng);i++) {
String temp = in.readUTF();
ctext[i] = Byte.parseByte(temp);
}
String check = in.readUTF();
// 获取密钥
FileInputStream f = new FileInputStream("sb.dat");
byte[] keysb = new byte[24];
f.read(keysb);
System.out.println("公共密钥:");
for (int i = 0;i<24;i++) {
System.out.print(keysb[i]+",");
}
System.out.println("");
SecretKeySpec k = new SecretKeySpec(keysb, "DESede");
// 解密
Cipher cp = Cipher.getInstance("DESede");
cp.init(Cipher.DECRYPT_MODE, k);
byte[] ptext = cp.doFinal(ctext);
System.out.println("");
// 显示明文
String p = new String(ptext, "UTF8");
String pMd5 = DigestPass.DP(p);
System.out.println("被解密明文的MD5值:"+pMd5);
if (pMd5.equals(check)){
System.out.println("和客户端的MD5值一致");
System.out.println("计算后缀表达式" + p);
out.writeUTF(mydc.evaluate(p)+"");
}
else {
System.out.println("警告:和客户端的MD5值不一致!");
}
} catch (Exception e) {
System.out.println("客户已断开" + e);
}
}
}
截图:
6(选做)
用Android Studio实现
总结
整个任务其实就是一环紧扣一环的,一层一层递进从而实现最后的部分,密码学部分的实现参照参考资料。
参考资料
20165326 java实验五的更多相关文章
- Java实验五
20145113 Java实验五 网络编程及安全 实验内容 对于客户端与服务器端:修改原代码,使其可以实现连续的传消息,并且传送文件. 对于加解密部分: 对于原先的加密只加密"hello w ...
- 20165310 Java实验五《网络编程与安全》
20165310 Java实验五<网络编程与安全> 任务一 题目:①编写MyBC.java实现中缀表达式转后缀表达式的功能:②编写MyDC.java实现从上面功能中获取的表达式中实现后缀表 ...
- 20165324 Java实验五 网络编程与安全
20165324 Java实验五 网络编程与安全 一.实验报告封面 课程:Java程序设计 班级:1653班 姓名:何春江 学号:20165324 指导教师:娄嘉鹏 实验日期:2018年5月28日 实 ...
- 2018-2019-2-20175323 java实验五 网络编程与安全
20175323 java实验五 网络编程与安全 任务一 ①编写MyBC.java实现中缀表达式转后缀表达式的功能 ②编写MyDC.java实现从上面功能中获取的表达式中实现后缀表达式求值的功能 基本 ...
- java实验五——字符数组、String、StringBuffer的相互转化,StringBuffer的一些方法
package hello; import java.util.Scanner; public class 实验五 { public static void main(String[] args) { ...
- java实验五实验报告
一.实验内容 Cmp传输与加解密 结对编程,一人服务器,一人客户端,服务器向客户端发送经RSA加密的密钥和用密钥加密的密文(使用DES算法),客户端负责接收加密后的密钥和密文,并解密得出明文. 二.实 ...
- Java实验五网络编程与安全
实验五 网络编程与安全 实验准备 博客 活动一 两人一组结对编程: 0. 参考http://www.cnblogs.com/rocedu/p/6766748.html#SECDSA 1. 结对实现中缀 ...
- 第七周学习总结&JAVA实验五报告。
JAVA实验报告五: 实验四 类的继承 实验目的 理解抽象类与接口的使用: 了解包的作用,掌握包的设计方法. 实验要求 掌握使用抽象类的方法. 掌握使用系统接口的技术和创建自定义接口的方法. 了解 J ...
- Java实验五参考答案
1.找错误 btOK.setOnAction( new EventHandler<ActionEvent> { public void handle (ActionEvent e) { S ...
随机推荐
- videojs+hls+rtmp流媒体播放
前言:刚接触前端,小白一个,如有出错,请指正,谢谢! 注:视频格式可以分为适合本地播放的本地影像视频和适合在网络中播放的网络流媒体影像视频两大类. 一.互联网网络流媒体简介 HTTP stream是各 ...
- 史上最全python面试题详解(一)(附带详细答案(持续更新))
1.简述解释型和编译型编程语言? 概念: 编译型语言:把做好的源程序全部编译成二进制代码的可运行程序.然后,可直接运行这个程序. 解释型语言:把做好的源程序翻译一句,然后执行一句,直至结束! 区别: ...
- MySQL查询命令_SELECT 子查询
首先创建一个table mysql> create table Total (id int AUTO_INCREMENT PRIMARY KEY,name char(20),stu_num in ...
- java开发中中文编码问题
//ajax以get方式提交,字符串中包含中文 //后台struts中对该string的set方法中 this.jsonString = new String(jsoString.getBytes(& ...
- redis工具
pom.xml添加 <!--jedis redis客户端--> <dependency> <groupId>redis.clients</groupId> ...
- opencv学习之路(19)、直方图
一.概述 二.一维灰度直方图 #include "opencv2/opencv.hpp" #include<iostream> using namespace cv; ...
- 获奖感想和python学习心得
一,获奖感想 很荣幸能成为小黄杉的获得者,也很感谢老师对我的这份鼓励和期望.回顾本学期的python学习中,我从一名对编程一无所知的小白,成为一名刚入门的程序猿.首先,我要感谢我的任课老师娄嘉鹏老师, ...
- bzoj2091: [Poi2010]The Minima Game DP
2091: [Poi2010]The Minima Game DP 链接 https://www.lydsy.com/JudgeOnline/problem.php?id=2091 思路 这类问题好迷 ...
- Swagger2使用参考
GitHub例子: 参考博客: https://blog.csdn.net/sanyaoxu_2/article/details/80555328 http://www.cnblogs.com/Joi ...
- wepy开发小程序eslint报错error 'getApp' is not defined no-undef
wepy开发小程序使用getApp().globalData保存全局数据很方便,但是会在控制台看到很多报错:“error 'getApp' is not defined no-undef”,这是esl ...