20175316 盛茂淞 2018-2019-2 《Java程序设计》实验五 《网络安全与编程》 实验报告
20175316 盛茂淞 2018-2019-2 《Java程序设计》实验五 《网络安全与编程》 实验报告
一、实验报告封面
课程:Java程序设计 班级:1753班 姓名:盛茂淞 学号:20175316
指导教师:娄嘉鹏 实验日期:2018年5月31日
实验时间:15:35 - 17:15 实验序号:五
实验名称: 网络编程与安全
实验目的:
1、掌握Java Socket的相关内容;
2、学会建立客户端与服务器端之间的联系;
3、学习并应用密码学的相关内容
二、实验内容
任务(一)
- 1、结对实现中缀表达式转后缀表达式的功能 MyBC.java
- 2、结对实现从上面功能中获取的表达式中实现后缀表达式求值的功能,调用MyDC.java
任务(二)
- 1、基于Java Socket实现客户端/服务器功能,传输方式用TCP
- 2、客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式通过网络发送给服务器
- 3、服务器接收到后缀表达式,调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
- 4、客户端显示服务器发送过来的结果
任务(三)
- 1、基于Java Socket实现客户端/服务器功能,传输方式用TCP
- 2、客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密后通过网络把密文发送给服务器
- 3、服务器接收到后缀表达式表达式后,进行解密(和客户端协商密钥,可以用数组保存),然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
- 4、客户端显示服务器发送过来的结果
任务(四)
- 1、基于Java Socket实现客户端/服务器功能,传输方式用TCP
- 2、客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文发送给服务器
- 3、客户端和服务器用DH算法进行3DES或AES算法的密钥交换
- 4、服务器接收到后缀表达式表达式后,进行解密,然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
- 5、客户端显示服务器发送过来的结果
任务(五)
- 1、基于Java Socket实现客户端/服务器功能,传输方式用TCP
- 2、客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文和明文的MD5値发送给服务器
- 3、客户端和服务器用DH算法进行3DES或AES算法的密钥交换
- 4、服务器接收到后缀表达式表达式后,进行解密,解密后计算明文的MD5值,和客户端传来的MD5进行比较,一致则调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
- 5、客户端显示服务器发送过来的结果
最后将每个任务的代码上传到码云。
三、实验步骤
任务(一)
任务(一)早在结队编程—四则运算中我们就已经实现了中缀转后缀的功能,以及将后缀表达式利用栈进行运算的功能。因此任务(一)我们直接在之前代码的基础上进行修改即可。
具体方法:
1.据表达式Exp = S1 + OP + S2(S1 ,S2是两个操作数,OP为运算符)有三种标识方法:
OP + S1 + S2 为前缀表示法
S1 + OP + S2 为中缀表示法
S1 + S2 + OP 为后缀表示法
2.中缀表达式转化成后缀表达式的过程:设立一个栈,存放运算符,首先栈为空;
从左到右扫描中缀式,若遇到操作数,直接输出,并输出一个空格作为两个操作数的分隔符;
若遇到运算符,则与栈顶比较,比栈顶级别高则进栈,否则退出栈顶元素并输出,然后输出一个空格作分隔符;
若遇到左括号,进栈;若遇到右括号,则一直退栈输出,直到退到左括号止。
当栈变成空时,输出的结果即为后缀表达式。
2.后缀表达式求值的步骤:设置一个操作数栈,开始栈为空;
从左到右扫描后缀表达式,遇操作数,进栈;
若遇运算符,则从栈中退出两个元素,先退出的放到运算符的右边,后退出的放到运算符左边,运算后的结果再进栈,直到后缀表达式扫描完毕。
此时,栈中仅有一个元素,即为运算的结果。
中缀转后缀代码
import java.util.*;
import java.lang.*;
public class MyBC{
String Normal;
String Behind= ""; //后序表示
int countLeft=0,countRight=0;
public void setNormal(String str){
Normal=str;
Behind="";
}
public void change(){
Stack stack=new Stack();
int opValue []=new int[100];
for (int i=0;i<Normal.length() ;i++) {
char chi=Normal.charAt(i);
if (chi>='0'&&chi<='9'){ //数字直接输出
Behind=Behind+chi;
}
else if (chi=='+'||chi=='-'||chi=='*'||chi=='÷'||chi=='/') { //如果是运算符的话:
Behind=Behind+" ";
if (stack.empty()){ //若栈为空,入栈
stack.push(chi);
}
else if (Value(chi)>Value((char)stack.peek())) { //若栈不空,那么比较优先级,如果优先级比栈顶元素高,入栈
stack.push(chi);
}
else{
Behind=Behind+ String.valueOf(stack.pop())+" ";//否则出栈输出
i--;
}
}
else if(chi=='('){
countLeft++;
stack.push(chi);//左括号直接压栈
}
else if(chi==')'){ //如果遇到右括号,不停出栈并输出直到遇到左括号,把左括号出栈
Behind+=" ";
countRight++;
while((char)stack.peek()!='('){
Behind=Behind+ String.valueOf(stack.pop())+" ";
}
stack.pop();
}
}
Behind+=" ";
while(!stack.empty()){
Behind=Behind+String.valueOf(stack.pop())+" ";
}
}
public int Value(char c){ //设定不同运算符的优先级
int value=0;
switch(c){
case '(':
value=1;
break;
case '+':
case '-':
value=2;
break;
case '*':
case '÷':
value=3;
break;
case '/':
value=4;
break;
case ')':
value=5;
default:
value=0;
}
return value;
}
}
- 求后缀表达式
import java.util.*;
public class Caculate {
public String caculate(String r){
Rational result=new Rational();
OutOfStack calculate=new OutOfStack();
result=calculate.evaluate(r); //运算出结果
int a=result.getNumerator();//获得结果的分子
int b=result.getDenominator();//获得结果的分母
if (b==1){
return String.valueOf(a);
}
else{
return String.valueOf(a)+"/"+String.valueOf(b);
}
}
}
代码运行结果如下,可以多种符号的四则运算。
任务(二)
通过java.net包中的Socket类和ServerSocket类来实现这个功能
套接字:IP地址表示计算机,端口号表示进程(线程),Socket类创建套接字对象并连接在一起(端口号与IP地址组合)。
客户端程序用Socket类创建负责连接到服务器的套接字对象,其构造方法为Socket([IP地址],[端口号])(可能抛出IOException异常)。对套接字对象建立后,可以使用
①getInputStream()获得一个输入流来读取服务器写入到输出流中的数据;②getOutputStream()获得一个输出流,服务器可以用输入流来读取客户写入到输出流中的数据。客户负责建立连接到服务器的套接字对象。服务器需要创建一个ServerSocket对象来将客户端的套接字对象与服务器的套接字对象连接起来。ServerSocket的构造方法是ServerSocket([端口号])(当端口已被占用会抛出IOException异常)。接着,ServerSocket对象调用accept()方法再次返回一个与客户端对象相连接的新的Socket对象。同样的,它也具有上述的两个方法。
从套接字连接中读取数据,可能在另一端数据发送之前就已经开始读取了,而且会阻塞本线程,直到成功读取到信息。同时,accept方法也会阻塞线程的执行,直到收到客户的呼叫。为了解决“收不到呼叫而导致程序无法继续运行”的情况,ServerSocket对象在调用accept方法之前可以先调用setTimeout(s)方法来使得在调用accept方法时如果超过s毫秒没有收到呼叫,就抛出SocketTimeoutException异常。
双方通信完毕,套接字要使用close()方法关闭套接字连接。
使用多线程技术:由于使用套接字连接中读取数据时,可能会阻塞本线程直到成功读取到信息。为了避免这种情况,需要启动一个专门为该客户服务的线程。Socket的构造方法Socket()可以创建一个套接字对象,该对象调用public void connect(SocketAddress endpoint) throws IOException来与指定的套接字创建连接。这里的参数可以使用InetSocketAddress的构造方法public InetSocketAdress(InetAdress addr,int port)来获得。套接字通信的两个基本原则:
①服务器要启动一个专门的线程与客户的套接字建立连接;
②套接字的输入流在读取信息时可能发生阻塞,所以客户端与服务器端都需要在一个单独的线程中读取信息。客户端关键代码
System.out.print("输入中缀表达式:");
while(scanner.hasNext()) {
String middle="";//初始化middle
try {
middle = scanner.next();//输入中缀表达式
}
catch(InputMismatchException exp){
System.exit(0);
}
try {
myBC.setNormal(middle);
myBC.change();//调用M有BC中的类来将中缀表达式转化为后缀表达式。
System.out.println("后缀表达式:"+myBC.Behind); //Behind是类变量,所以可以通过类名来调用。
out.writeUTF(myBC.Behind);//将后缀表达式写进流中
}
catch(Exception e) {}
}
- Read类输出结果
...
public void run() {
String result="";
while(true) {
try{ result=in.readUTF();//读取从服务器端传输回来的结果
System.out.println("结果:"+result);
System.out.println("输入中缀表达式:");//可以再次输入新的表达式进行运算。
}
catch(IOException e) {
System.out.println("与服务器已断开"+e);
break;
}
}
}
...
- 服务器端关键代码
...
@Override
public void run() {
while(true) {
try{ String r=in.readUTF();//堵塞状态,除非读取到信息
String result=caculate.caculate(r);//调用Caculate类进行运算
out.writeUTF(result);//将结果写入到流中
}
catch (IOException e) {
System.out.println("客户离开");
return;
}
}
}
...
- 运行代码
- 客户端截图
- 服务器端截图
任务(三)
- 参考了之前实验三时娄老师的博客:Java 密码学算法,使用了DES算法。
- 加密部分代码
...
String cipher=sEnc.Cipher(myBC.Behind);//将后缀表达式加密
out.writeUTF(cipher);//将加密结果写入到流中让服务器端读取
...
- 解密部分代码
...
String r=in.readUTF();//读取客户端传过来的密文
String plain=sDec.Plain(r);//解密
String result=caculate.caculate(plain);//将解密得到的后缀表达式进行计算,然后返回计算结果。
...
- 运行截图
客户端
服务器端
任务(四)
关于DH算法
- Diffie-Hellman是一种建立密钥的方法,而不是加密方法。然而,它所产生的密钥可用于加密、进一步的密钥管理或任何其它的加密方式。
- 基于原根的定义及性质,可以定义Diffie-Hellman密钥交换算法.该算法描述如下:
1,有两个全局公开的参数,一个素数q和一个整数a,a是q的一个原根.
2,假设用户A和B希望交换一个密钥,用户A选择一个作为私有密钥的随机数XA(XA<q),并计算公开密钥YA=a^XA mod q。A对XA的值保密存放而使YA能被B公开获得。类似地,用户B选择一个私有的随机数XB<q,并计算公开密钥YB=a^XB mod q。B对XB的值保密存放而使YB能被A公开获得。
3,用户A产生共享秘密密钥的计算方式是K = (YB)^XA mod q.同样,用户B产生共享秘密密钥的计算是K = (YA)^XB mod q.这两个计算产生相同的结果: K = (YB)^XA mod q = (a^XB mod q)^XA mod q = (aXB)XA mod q (根据取模运算规则得到) = a^(XBXA) mod q = (aXA)XB mod q = (a^XA mod q)^XB mod q = (YA)^XB mod q 因此相当于双方已经交换了一个相同的秘密密钥.
4,因为XA和XB是保密的,一个敌对方可以利用的参数只有q,a,YA和YB.因而敌对方被迫取离散对数来确定密钥.例如,要获取用户B的秘密密钥,敌对方必须先计算 XB = inda,q(YB) 然后再使用用户B采用的同样方法计算其秘密密钥K. Diffie-Hellman密钥交换算法的安全性依赖于这样一个事实:虽然计算以一个素数为模的指数相对容易,但计算离散对数却很困难.对于大的素数,计算出离散对数几乎是不可能的. 下面给出例子.密钥交换基于素数q = 97和97的一个原根a = 5.A和B分别选择私有密钥XA = 36和XB = 58.每人计算其公开密钥 YA = 5^36 = 50 mod 97 YB = 5^58 = 44 mod 97 在他们相互获取了公开密钥之后,各自通过计算得到双方共享的秘密密钥如下: K = (YB)^XA mod 97 = 44^36 = 75 mod 97 K = (YA)^XB mod 97 = 50^58 = 75 mod 97 从|50,44|出发,攻击者要计算出75很不容易。
客户端运行截图
服务器端运行截图
任务(五)
在任务(四)的基础上引入MD5算法加密的类,调用其他的函数,参数为要加密的字符串,返回加密后的字符串。
加密代码
...
public String MD5(String cipher) throws Exception{
MessageDigest m=MessageDigest.getInstance("MD5");
m.update(cipher.getBytes("UTF8"));
byte s[ ]=m.digest( );
String result="";
for (int i=0; i<s.length; i++){
result+=Integer.toHexString((0x000000ff & s[i]) |
0xffffff00).substring(6);//将加密结果转化为16进制字符串
}
System.out.println("MD5加密后的结果:"+result);//输出加密后的结果
return result;//返回加密后的结果。
...
- 服务器端中改动的代码:
...
String r=in.readUTF();//读取信息到r中(r是密文)
String plain=sDec.Plain(r);//将r解密得到明文
String message=digestPass.MD5(plain);//将解密后得到的明文用MD5算法加密,放入message中
String result=caculate.caculate(plain);//将解密后得到的算式进行运算
String q=in.readUTF();//得到用户端传送过来用MD5加密的明文q。
if(message.equals(q)){ //比较message和q,如果相等则校验成功,将计算结果返回。
System.out.println("校验成功!");
out.writeUTF(result);
...
- 客户端中改动的代码:
...
String cipher=sEnc.Cipher(myBC.Behind);//将后缀表达式使用DES算法加密,得到密文cipher
out.writeUTF(cipher);把密文cipher写入流中以让服务器端读取。
out.writeUTF(digestPass.MD5(myBC.Behind));//将后缀表达式(明文)使用MD5算法加密,然后写入流中以让服务器端读取。
- 客户端截图
- 服务器端截图
四、码云链接
https://gitee.com/shengmaosong/java-besti-20175316/tree/master/shiyan5
五、实验过程中所遇到的问题
- 问题一:在调试过程中,服务器端会出现
Exception in thread "main" java.lang.NullPointerExcption
从而导致监听不成功
解决办法:原因是我没有将之前的服务器端口关闭,而是开了多个服务器端口,却使用了同样的端口,所以导致了这个情况。把之前的端口先关掉,问题就解决了。
六、实验感悟
- 本次实验让我对网络编程与安全有了初步的了解,同时对于Java的密码学应用相比之前有了更深刻的认识。这次实验让我在Java、计算机网络、密码学三个方面有所学习有所进步,可以说是一举三得。因此我觉得这是一次很有意义的实验。
20175316 盛茂淞 2018-2019-2 《Java程序设计》实验五 《网络安全与编程》 实验报告的更多相关文章
- 20175316盛茂淞-Java第1周学习总结
20175316盛茂淞 2018-2019-2 <Java程序设计>第1周学习总结 教材学习内容总结 Java入门 1.Java简介(地位,特点) 2.安装JDK,设置系统环境 3.编译J ...
- 20175316盛茂淞 2018-2019-2 《Java程序设计》第9周学习总结
20175316盛茂淞 2018-2019-2 <Java程序设计>第9周学习总结 教材学习内容总结 下载安装MySQL数据库管理系统. 学习<Java程序设计>第十一章MyS ...
- 20175316盛茂淞 2018-2019-2 《Java程序设计》第8周学习总结
20175316盛茂淞 2018-2019-2 <Java程序设计>第8周学习总结 教材学习内容总结 第十五章 泛型 -- 主要目的是可以建立具有类型安全的集合框架,如链表.散列映射等数据 ...
- 20175316 盛茂淞 2018-2019-2 《Java程序设计》实验二 面向对象程序设计 实验报告
20175316 盛茂淞 2018-2019-2 <Java程序设计>实验二 面向对象程序设计 实验报告 (一)单元测试 在 IDEA中我们把产品代码放在src目录中,把测试代码放在tes ...
- 20175316盛茂淞 2018-2019-2 《Java程序设计》第7周学习总结
20175316盛茂淞 2018-2019-2 <Java程序设计>第7周学习总结 教材学习内容总结 第八章 常用实用类 一.String类 String类在java.lang包中,jav ...
- 20175316盛茂淞 2018-2019-2 《Java程序设计》第6周学习总结
20175316盛茂淞 2018-2019-2 <Java程序设计>第6周学习总结 教材学习内容总结 第7章 内部类与异常类 1.使用 try.catch Java中所有信息都会被打包为对 ...
- 20175316 盛茂淞 2018-2019-2 《Java程序设计》实验一 Java开发环境的熟悉 实验报告
20175316 盛茂淞 2018-2019-2 <Java程序设计>实验一 Java开发环境的熟悉 实验报告 一.实验要求 1.使用JDK编译.运行简单的Java程序: 2.使用IDEA ...
- 20175316盛茂淞 2018-2019-2 《Java程序设计》第5周学习总结
20175316盛茂淞 2018-2019-2 <Java程序设计>第5周学习总结 教材学习内容总结 第六章 接口与实现. 何谓接口 接口:书上没有明确地给出接口的定义,我理解的接口就是一 ...
- 20175316盛茂淞 2018-2019-2《Java程序设计》第4周学习总结
20175316盛茂淞 2018-2019-2<Java程序设计>第4周学习总结 教材学习内容总结 第五章 子类与继承 一.继承 1.继承定义:避免多个类间重复定义共同行为 2.子类与父类 ...
随机推荐
- 怎么联系$zcy$呢?
\(QQ:2939533969\) \(luogu:\)little_sun 窝经常以little_sun,little_sun0331,zcy05331的昵称混迹于各大网站 窝的CSDN blog ...
- TensorFlow(十一):递归神经网络(RNN与LSTM)
RNN RNN(Recurrent Neural Networks,循环神经网络)不仅会学习当前时刻的信息,也会依赖之前的序列信息.由于其特殊的网络模型结构解决了信息保存的问题.所以RNN对处理时间序 ...
- 爬虫(十):scrapy命令行详解
建爬虫项目 scrapy startproject 项目名例子如下: localhost:spider zhaofan$ scrapy startproject test1 New Scrapy pr ...
- java23种设计模式等等。。
23种设计模式http://www.cnblogs.com/maowang1991/archive/2013/04/15/3023236.html 提升Java代码性能和安全性https://blog ...
- vue+elementui 开发的网站IE浏览器加载白屏(不兼容)解决办法
1.需要检查一下 export default { name: 'aa',-------vue的name是不可以重复的-----这个是决定性原因 data() { return {} } 2.变量声明 ...
- Hbuild在线云ios打包失败,提示BuildConfigure Failed 31013 App Store 图标 未找到 解决方法
用 hbuild 打 IOS 包,打包失败,提示以下错误: manifest.plus.plugins.push.igexin;manifest.plus.plugins.oauth.weixin; ...
- python3编程基础之一:标识符
每种编程语言都是需要处理数据的,需要变量.函数.类等,而这些都是通过名称访问的.因此,能够作为变量.函数.类等名称的字符串就是标识符.数据,是计算机进行运算的实体.标识符,用来标记的符号,它会指向一个 ...
- secureCRT操作redis-cli时, 不断追加ip:port
Session Options-->Terminal-->Emulation-->Terminal为Linux
- ArcGIS10.3_解决属性表中文乱码问题
借鉴前辈们解决ArcMap低版本属性表乱码的问题解决方法,勇敢的尝试了一下Pro中的解决方法,其实道理都一样.先来看看第一种方法:打开CMD,如果是ArcMap,输入如下命令: reg add HKE ...
- webpack介绍和使用
一webpack介绍1由来2介绍3作用4拓展说明5webpack整体认知二webpack安装1安装node2安装cnpm3安装nrm的两种方法4安装webpack三webpack配置0搭建项目结构1初 ...