20202309葛鹏宇《数据结构与面向对象程序设计》实验4实验报告
# 20202309 2021-2022-1 《数据结构与面向对象程序设计》实验4报告
课程:《程序设计与数据结构》
班级: 2023
姓名: 葛鹏宇
学号:20202309实验教师:王志强 实验日期:2020年10月24日
必修/选修: 必修
## 1.实验内容
(一)Java Socket编程
1.学习蓝墨云上教材《Java和Android编程》“第16章 输入/输出 ”和“第22章 网络”,学习JavaSocket编程
2.结对编程。结对伙伴A编写客户端SocketClient.java,结对伙伴B编写服务器端。
3.截图加学号水印上传蓝墨云,代码push到码云,并撰写实验报告。
(二)Java和密码学
参考 http://www.cnblogs.com/rocedu/p/6683948.html
以结对的方式完成Java密码学相关内容的学习(帖子中所有代码和相关知识点需要学习)。提交学习成果码云链接和代表性成果截图,要有学号水印。
(三)编写有理数/复数计算器
结对编程,结对伙伴A编写有理数计算器。结对伙伴B编写复数计算器。截图加水印上传蓝墨云,代码push码云。
(四)远程有理数计算器
结对编程,结对伙伴A编程实现客户端,结果伙伴B实现服务器端。
客户端通过键盘输入一个有理数计算的公式(例如:1/4 + 1/6 = ),并把该公式以字符串的形式发送给伙伴B(服务器端),服务器端根据字符串计算出结果为5/12,并把结果返回给客户端A,A收到结果后输出结果。截图加水印上传蓝墨云,代码push码云。
(五)远程复数计算器
结对编程,结对伙伴B编程实现客户端,结果伙伴A实现服务器端。
客户端通过键盘输入一个有理数计算的公式(例如:1/4 + 1/6 = ),并把该公式以字符串的形式发送给伙伴A(服务器端),服务器端根据字符串计算出结果为5/12,并把结果返回给客户端B,B收到结果后输出结果。截图加水印上传蓝墨云,代码push码云。
注意实验四(4)和实验四(5),一个人不能仅实现客户端,必须实现一个客户端和服务器,否则两个实验均不得分!!!
(六)实验报告
在规定时间前发表博客,标题“学号 实验四 《数据结构与面向对象程序设计》实验报告”
## 2. 实验过程及结果
(一)Java Socket编程
public class Client { public static void main(String[] args) throws IOException { //建立客户端,host为伙伴的IP地址 Socket socket = new Socket("172.20.10.13",8800); //输入流 InputStream inputStream = socket.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8")); //输出流,获取socket读写流 OutputStream outputStream = socket.getOutputStream(); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream); //利用流按照一定的操作,传递信息,对socket进行读写操作 String message1 = "用户名:Username 密码:2023"; outputStreamWriter.write(message1); outputStreamWriter.flush(); socket.shutdownOutput(); //接受响应 String reply = null; while (!((reply = bufferedReader.readLine())==null)){ System.out.println(reply); } //关闭资源 bufferedReader.close(); inputStream.close(); outputStreamWriter.close(); outputStream.close(); } }
import java.net.*; import java.io.*; public class Server { public static void main(String[] args) throws IOException { //建立服务器绑定窗口 ServerSocket serverSocket = new ServerSocket(8800); //accept()方法处理连接请求,防止非法监听 Socket socket = serverSocket.accept(); //输入流 InputStream inputStream = socket.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); //输出流 OutputStream outputStream = socket.getOutputStream(); PrintWriter printWriter = new PrintWriter(outputStream); //读取用户信息 String message = null; System.out.println("服务器建立中"); //反馈信息 while (!((message=bufferedReader.readLine())==null)){ System.out.println("这里是服务器,接受的信息为:"+message); } String reply = "Hello!"; //传递信息 printWriter.write(reply); printWriter.flush(); //关闭资源 inputStream.close(); outputStream.close(); bufferedReader.close(); printWriter.close(); serverSocket.close(); socket.close(); } }
(二)Java和密码学
凯撒密码:
public class MimaTest { public static void main(String[] args) throws Exception{ String s="Hello World"; int key=4; char[] chars=s.toCharArray(); StringBuilder newchars=new StringBuilder(); for(int i=0;i<s.length();i++) { int c=chars[i]; if(c>='a' && c<='z') //小写 { c+=key%26; //移动位数 if(c<'a') c+=26; if(c>'z') c-=26; } else if(c>='A' && c<='Z') //大写 { c+=key%26; if(c<'A') c+=26; if(c>'Z') c-=26; } char cc=(char)c; newchars.append(cc); } System.out.println(newchars); } }
DES:
import java.io.*; import javax.crypto.*; public class DESkey { public static void main(String args[]) throws Exception{ KeyGenerator kg=KeyGenerator.getInstance("DESede"); kg.init(168); SecretKey aa=kg.generateKey( ); FileOutputStream bb=new FileOutputStream("key1.dat"); ObjectOutputStream b=new ObjectOutputStream(bb); b.writeObject(aa); } }
import java.io.*; import java.security.*; public class DESkeyy{ public static void main(String[] args) throws Exception{ FileInputStream f=new FileInputStream("key1.dat"); ObjectInputStream b=new ObjectInputStream(f); Key k=(Key)b.readObject(); byte[] kb=k.getEncoded(); FileOutputStream f2=new FileOutputStream("key11.dat"); f2.write(kb); for(int i=0;i<kb.length;i++){ System.out.print(kb[i]+","); } } }
import java.io.*; import java.security.*; import javax.crypto.*; public class DESadd { public static void main(String[] args) throws Exception{ FileInputStream f=new FileInputStream("key1.dat"); ObjectInputStream b=new ObjectInputStream(f); Key k=(Key)b.readObject( ); Cipher cc=Cipher.getInstance("DESede"); cc.init(Cipher.ENCRYPT_MODE, k); String s="JAVA"; byte xx[]=s.getBytes("UTF8"); for(int i=0;i<xx.length;i++){ System.out.print(xx[i]+","); } System.out.println(""); byte mm[]=cc.doFinal(xx); for(int i=0;i<mm.length;i++){ System.out.print(mm[i] +","); } FileOutputStream f2=new FileOutputStream("key2.dat"); f2.write(mm); } }
import java.io.*; import javax.crypto.*; import javax.crypto.spec.*; public class DESdecode{ public static void main(String[] args) throws Exception{ FileInputStream k=new FileInputStream("key2.dat"); int num=k.available(); byte[] ctext=new byte[num]; k.read(ctext); FileInputStream kk=new FileInputStream("key11.dat"); int num2=kk.available(); byte[] keykb=new byte[num2]; kk.read(keykb); SecretKeySpec t=new SecretKeySpec(keykb,"DESede"); Cipher cp=Cipher.getInstance("DESede"); cp.init(Cipher.DECRYPT_MODE,t); byte[] ptext=cp.doFinal(ctext); String p=new String(ptext,"UTF8"); System.out.println(p); } }
MD5:
import java.security.*; public class MD5 { public static void main(String[] args) throws Exception{ String x=args[0]; MessageDigest m=MessageDigest.getInstance("MD5"); m.update(x.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); } System.out.println(result); } }
(三)编写有理数/复数计算器
import java.util.Scanner; public class YouLiShu{ public static void main(String[] args) { double a,b,c=0; char d; char sign; Scanner scan = new Scanner(System.in); do { System.out.println("请输入第一个有理数:"); a = scan.nextFloat(); System.out.println("请输入第二个有理数:"); b = scan.nextFloat(); System.out.printf("第一个有理数"+"%.6f\n",a); System.out.printf("第二个有理数:"+"%.6f\n",b); System.out.println("请输如要运算的符号"); sign = scan.next().charAt(0); switch (sign) { case '+': c = a+b; break; case '-': c = a-b; break; case '*': case 'x': case 'X': c = a*b; break; case '/': c = a/b; break; default: break; } System.out.println("a" + sign + "b = " + c); System.out.println("是否继续?是输入Y否输入N"); d= scan.next().charAt(0); }while(d=='Y'); } }
import java.util.StringTokenizer; public abstract class Wulishu { static double a,b,c,d; double RealPart; double ImagePart; static String choose; public static char ch; public void Add() { RealPart = a + c; ImagePart = b + d; } public void Sub() { RealPart = a - c; ImagePart = b - d; } public void Mul() { RealPart = a*c - b*d; ImagePart = b*c + a*d; } public void Div() { RealPart = (a*c + b*d)/(c*c + d*d); ImagePart = (b*c + a*d)/(c*c + d*d); } public String toString(String s) { if(ImagePart >= 0){ return s + "=" + RealPart + "+" + ImagePart + "i"; }else { return s + "=" + RealPart +""+ ImagePart + "i"; } } public void Faction(String f){ char z; StringTokenizer st = new StringTokenizer(f, " ", false); z = st.nextToken().charAt(0); a = Double.parseDouble(st.nextToken()); z = st.nextToken().charAt(0); b = Double.parseDouble(st.nextToken()); z = st.nextToken().charAt(0); z = st.nextToken().charAt(0); ch = st.nextToken().charAt(0); z = st.nextToken().charAt(0); c = Double.parseDouble(st.nextToken()); z = st.nextToken().charAt(0); d = Double.parseDouble(st.nextToken()); } }
import java.util.Scanner; public class WulishuTest extends Wulishu { public static void main(String[] args) { String next = "y"; String s; do{ Scanner scan = new Scanner(System.in); System.out.println("请输入复数运算式,各符号数字间用空格隔开,负数除外(如:( 1 + 2 i ) + ( 2 + -3 i ) ):"); Wulishu ff; ff = new WulishuTest(); s = scan.nextLine(); ff.Faction(s); Wulishu count; count = new WulishuTest(); switch (ch){ case '+': { count.Add(); break; } case '-': { count.Sub(); break; } case '*': { count.Mul(); break; } case '/': { count.Div(); break; } default: System.out.println("Illegal input!"); break; } System.out.println(count.toString(s)); System.out.print("如果您想要继续计算,请输入y,否则输入其他: "); choose = scan.nextLine(); }while(choose.equals(next)); } }
(四)远程有理数计算器
import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.StringTokenizer; public class Server2 { private static fenshu frac2; private static fenshu frac1; private static String a,b; private static char ch; private static fenshu result = null; public static void main(String[] args) throws IOException { ServerSocket serverSocket=new ServerSocket(8809); Socket socket=serverSocket.accept(); InputStream inputStream=socket.getInputStream(); BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(inputStream)); OutputStream outputStream=socket.getOutputStream(); PrintWriter printWriter=new PrintWriter(outputStream); String info=null; System.out.println("服务器已经建立......"); while(!((info = bufferedReader.readLine()) ==null)){ System.out.println("我是服务器,用户的加密信息为:" + info); String s= info; String es=""; int key = -4; for(int i=0;i<s.length( );i++) { char c=s.charAt(i); if(c>=0 && c<=127) { c+=key%26; if(c<0) c+=127; if(c>127) c-=127; } es+=c; } System.out.println("我是服务器,用户的解密后的信息为:" + es); StringTokenizer st = new StringTokenizer(es, " ", false); a=st.nextToken(); ch=st.nextToken().charAt(0); b=st.nextToken(); frac1=new fenshu(a); frac2=new fenshu(b); switch (ch) { case '+': result=frac1.getJia(frac2); break; case '-': result=frac1.getJian(frac2); break; case '*': result=frac1.getCheng(frac2); break; case '/': result=frac1.getChu(frac2); break; default: break; } } //给客户一个响应 String reply=frac1+String.valueOf(ch)+frac2+"="+result; String z= reply; String tes=""; int key = 4; for(int j=0;j<z.length( );j++) { char d=z.charAt(j); if(d>=0 && d<=127) { d+=key%26; if(d<0) d+=127; if(d>127) d-=127; } tes+=d; } printWriter.write(tes); printWriter.flush(); //5.关闭资源 printWriter.close(); outputStream.close(); bufferedReader.close(); inputStream.close(); socket.close(); serverSocket.close(); } }
import java.util.StringTokenizer; public class fenshu { int fenzi,fenmu; char ch; public fenshu(String str) { StringTokenizer st=new StringTokenizer(str,"/",true); this.fenzi = Integer.parseInt(st.nextToken()); this.ch=st.nextToken().charAt(0); this.fenmu = Integer.parseInt(st.nextToken()); } public fenshu yuefen(int fz,int fm){ int i; for (i=2;i<=fz&&i<=fm;i++){ if(fz%i==0&&fm%i==0){ fz=fz/i; fm=fm/i; } } fenshu result=new fenshu(fz+"/"+fm); return result; } public fenshu getJia(fenshu x){ int newFenmu=this.fenmu*x.fenmu; int newFenzi=fenzi*x.fenmu+x.fenzi*fenmu; return yuefen(newFenzi,newFenmu); } public fenshu getJian(fenshu x){ int newFenmu=fenmu*x.fenmu; int newFenzi=fenzi*x.fenmu-x.fenzi*fenmu; return yuefen(newFenzi,newFenmu); } public fenshu getCheng(fenshu x){ int newFenmu=fenmu*x.fenmu; int newFenzi=fenzi*x.fenzi; return yuefen(newFenzi,newFenmu); } public fenshu getChu(fenshu x){ int newFenmu=fenmu*x.fenzi; int newFenzi=fenzi*x.fenmu; return yuefen(newFenzi,newFenmu); } @Override public String toString() { return fenzi + "/" + fenmu; } }
(五)远程复数计算器
import java.io.*; import java.net.Socket; public class Client3 { public static void main(String[] args) throws IOException { Socket socket = new Socket("192.168.191.243",8800); InputStream inputStream = socket.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8")); OutputStream outputStream = socket.getOutputStream(); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream); String s= "( 1 + 2 i ) + ( 1 + -2 i )"; int key=4; String es=""; for(int i=0;i<s.length( );i++){ char c=s.charAt(i); if(c>='a' && c<='z') { c+=key%26; if(c<'a') c+=26; if(c>'z') c-=26; } else if(c>='0' && c<='9') { c+=key%10; if(c<'0') c+=10; if(c>'9') c-=10; } else if(c>='*' && c<='/') { c+=key%6; if(c<'*') c+=6; if(c>'/') c-=6; } es+=c; } System.out.println(es); String info1 = es; outputStreamWriter.write(info1); outputStreamWriter.flush(); socket.shutdownOutput(); //接受响应 String reply = null; while (!((reply = bufferedReader.readLine())==null)){ System.out.println(reply); } //关闭资源 bufferedReader.close(); inputStream.close(); outputStreamWriter.close(); outputStream.close(); } }
## 3. 实验过程中遇到的问题和解决过程
- 问题1:在与结对伙伴联机时,总是连接超时。
- 问题1解决方案:在询问同学后发现是没有连在一个共同的网络上,改为连接一个网络上就成功了。
## 其他(感悟、思考等)
这次的实验内容涉及了密码学,虽然在信息传递的时候加上密码实现起来复杂不少,但是我们了解并且会使用它很有必要。
## 参考资料
- [《Java程序设计与数据结构教程(第四版)》]