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程序设计与数据结构教程(第四版)》]

posted @ 2021-10-24 23:09  20202309葛鹏宇  阅读(35)  评论(0编辑  收藏  举报