zoukankan      html  css  js  c++  java
  • 实验四

    学号 2019-2020-182321 《数据结构与面向对象程序设计》实验四报告

    课程:《程序设计与数据结构》

    班级: 1823

    姓名: 杨凯涵

    学号:20182321

    实验教师:王志强

    实验日期:2019年10月7日

    必修/选修: 必修

    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编写复数计算器
    • 实验四:远程有理数计算器,结对编程,结对伙伴A编程实现客户端,结果伙伴B实现服务器端。
      客户端通过键盘输入一个有理数计算的公式(例如:1/4 + 1/6 = ),并把该公式以字符串的形式发送给伙伴B(服务器端),服务器端根据字符串计算出结果为5/12,并把结果返回给客户端A,A收到结果后输出结果。截图加水印上传蓝墨云,代码push码云。
    • 实验五:远程有理数复数计算器,结对编程,结对伙伴B编程实现客户端,结果伙伴A实现服务器端。
      客户端通过键盘输入一个有理数计算的公式(例如:1/4 + 1/6 = ),并把该公式以字符串的形式发送给伙伴A(服务器端),服务器端根据字符串计算出结果为5/12,并把结果返回给客户端B,B收到结果后输出结果。截图加水印上传蓝墨云,代码push码云

    2实验过程及结果

    实验一

    学习javasocket编程,并与结对小伙伴一个实现服务端,一个实现客户端。


    通过以上的学习,我们知道,socket无外乎就是一个借口,SSocket就像是发动机,提供了网络通信的能力。由此,我们利用老师给我们的代码
    服务器:

    package HttpSocket;
    
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /**
     * Created by besti on 2019/9/29.
     */
    public class Server1823 {
        public static void main(String[] args) throws IOException {
            //1.建立一个服务器Socket(ServerSocket)绑定指定端口
            ServerSocket serverSocket=new ServerSocket(8800);
            //2.使用accept()方法阻止等待监听,获得新连接
            Socket socket=serverSocket.accept();
            //3.获得输入流
            InputStream inputStream=socket.getInputStream();
            BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(inputStream));
            //获得输出流
            OutputStream outputStream=socket.getOutputStream();
            PrintWriter printWriter=new PrintWriter(outputStream);
            //4.读取用户输入信息
            String info=null;
            System.out.println("服务器已经建立......");
            while(!((info = bufferedReader.readLine()) ==null)){
                System.out.println("我是服务器,用户信息为:" + info);
            }
            //给客户一个响应
            String reply="welcome";
            printWriter.write(reply);
            printWriter.flush();
            //5.关闭资源
            printWriter.close();
            outputStream.close();
            bufferedReader.close();
            inputStream.close();
            socket.close();
            serverSocket.close();
        }
    }
    
    

    客户端:

    package HttpSocket;
    
    import com.sun.corba.se.impl.orbutil.ObjectUtility;
    
    import java.io.*;
    import java.net.Socket;
    
    /**
     * Created by besti on 2018/6/9.
     */
    public class SocketClient {
        public static void main(String[] args) throws IOException {
            //1.建立客户端Socket连接,指定服务器位置和端口
            Socket socket = new Socket("localhost",8800);
    //        Socket socket = new Socket("172.16.43.187",8800);
    
            //2.得到socket读写流
            OutputStream outputStream = socket.getOutputStream();
     //       PrintWriter printWriter = new PrintWriter(outputStream);
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
            //输入流
            InputStream inputStream = socket.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
            //3.利用流按照一定的操作,对socket进行读写操作
            String info1 = " 用户名:Tom,密码:123456";
    //        String info = new String(info1.getBytes("GBK"),"utf-8");
       //     printWriter.write(info);
       //     printWriter.flush();
            outputStreamWriter.write(info1);
            outputStreamWriter.flush();
            socket.shutdownOutput();
            //接收服务器的响应
            String reply = null;
            while (!((reply = bufferedReader.readLine()) ==null)){
                System.out.println("接收服务器的信息为:" + reply);
            }
            //4.关闭资源
            bufferedReader.close();
            inputStream.close();
            outputStreamWriter.close();
            //printWriter.close();
            outputStream.close();
            socket.close();
        }
    }
    
    

    在读取用户信息之前,我们是要建立一个接口,绑定一个端口,并且创建输出流和输入流的对象,这样两个程序之间的连接就算是做好了,接着作为服务器,就要从客户端出接受信息,这里用bufferedReader.readLine()来进行获取,而客户端是用outputStreamWriter.write来进行输出(这两个输入输出的对象在此之前已经建立),往下走,服务器再返回客户端一个信息(使用printWriter.write()),而客户端接受信息后就显示出来,最后再关闭我们的客户端和服务器。(运行结果中的乱码只需要把UTF-8挑为GBK就好了)。

    实验二

    Java和密码学:
    根据楼老师的博客操作:

    1. 凯撒密码:先约定好将明文往后移动多少个字母,然后对明文进行加密。如:YKH加密后为AOJ。我们的代码如下
    public static void main(String args[]) throws Exception{
    String s=args[0];
            int key=Integer.parseInt(args[1]);
            String es="";
            for(int i=0;i<s.length( );i++)
    {  char c=s.charAt(i);
                   if(c>='a' && c<='z') // 是小写字母
                      { c+=key%26;  //移动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;
                      }
                   es+=c;
               }
           System.out.println(es);
         }
    

    运行截图:

    在这个地方输入我们要加密的内容,然后往后移动四位的意思。

    1. Java对称加密-DES算法
      运行截图:
      运行DES程序,得到密钥key1.dat

    保存密钥编码格式,在程序中输入java Skey_kb,在程序的当前目录中将产生文件名为keykb1.dat的文件,运行结果如下:

    处理加密结果:

    最终进行解密:

    1. Java非对称加密-RSA算法:
      在凯撒密码里提到的老地方输入java Skey_RSA,运行RSA从而生成公钥和私钥。

    继续输入java Skey_RSA,运行Enc RsA程序,得到如下结果:![]

    这都显示了公钥中的参数以及加密的结果c。

    接着运行程序输入java Dec_RSA运行DecRsa程序,得到如下结果:
    其中显示了私钥中的参数以及解密的结果,其中整型的明文转换后显示出字符串“Hello World!”。

    1. 使用密钥协定创建共享密钥
      建立A、B两个文件夹,然后分别在里面输入“java Key_DH Apub.dat Apri.dat”和“java Key_DH Bpub.dat Bpri.dat”运行,运行结果如图所示:

    将程序KeyAgree编译后分别拷贝在A和B两个目录,首先在A目录输入“java KeyAgree Bpub.dat Apri.dat”运行程序,它使用文件Bpub.dat中对方的公钥和文件Apri.dat中自己的私钥创建了一段共享的字节数组。

    实验三

    根据要求,我编写了一个计算器如图:

    实验四

    编写远程有理数计算器,我们编写了两个类,一个rational类,一个script类,rational用来进行有理数计算,而script用来讲客户输入的字符串转换成double输入到rational中。以下为代码

    rational.java
    package com.company;
    
    public class Rational {
        private int numerator ,denominator;
        public Rational(int numer,int denom)
        {
            if(denom == 0)
                denom = 1;
            if(denom < 0)
            {
                numer = numer * -1;
                denom = denom * -1;
            }
            numerator = numer;
            denominator = denom;
            reduce();
        }
    
    
    public int getNumerator()
    {
        return numerator;
    }
    public int getDemoninator()
    {
        return denominator;
    }
    public Rational reciprocal()
    {
        return new Rational(denominator,numerator);
    }
    public  Rational add (Rational op2)
    {
        int commonDenominator = denominator*op2.getDemoninator();
        int numerator1 = numerator*op2.getDemoninator();
        int numerator2 = op2.getNumerator()*denominator;
        int sum = numerator1 + numerator2;
        return new Rational(sum,commonDenominator);
    }
    public Rational subtract (Rational op2)
    {
        int commonDenominator = denominator*op2.getDemoninator();
        int numerator1 = numerator*op2.getDemoninator();
        int numerator2 = op2.getNumerator()*denominator;
        int difference = numerator1 - numerator2;
        return  new Rational(difference,commonDenominator);
    }
    public Rational multipy(Rational op2)
    {
        int numer = numerator* op2.getNumerator();
        int denom = denominator*op2.getDemoninator();
        return new Rational(numer,denom);
    }
    public Rational divide (Rational op2)
    {
        return multipy(op2.reciprocal());
    }
    public String toString()
    {
        String result;
        if (numerator == 0)
        {
            result = "0";
        }
        else
            if(denominator == 1)
            {
                result = numerator + "";
            }
            else
                result = numerator +"/"+denominator;
            return result;
    }
    private void reduce()
    {
        if (numerator != 0)
        {
            int common =gcd (Math.abs(numerator),denominator);
            numerator = numerator/common;
            denominator = denominator / common;
        }
    }
    private int gcd (int num1, int num2)
    {
        while (num1 != num2)
            if(num1>num2)
                num1 = num1 - num2;
            else
                num2= num2-num1;
            return  num1;
    }
    }
    
    package com.company;
    public class script
    {
        private String s ;
        public script(String s)
        {
            this.s=s;
        }
    public  String getresult()
    {
        String[] a1 = s.split("\*|\+|-|/");
    
        String reply = "";
        int a, b, c, d;
        a = Integer.parseInt(a1[0]);
        b = Integer.parseInt(a1[1]);
        c = Integer.parseInt(a1[2]);
        d = Integer.parseInt(a1[3]);
        Rational rational = new Rational(a,b );
        Rational rational1 = new Rational(c,d);
        int i = 0;
        int n = 0;
        char[] e = s.toCharArray();
        for (i = 0; i < e.length; i++) {
            if (e[i] == '+') {
                reply = rational.add(rational1).toString();
            } else if (e[i] == '-') {
                reply = rational.subtract(rational1).toString();
            } else if (e[i] == '*') {
                reply = rational.multipy(rational1).toString();
            } else if (e[i]=='/')
            {
                n++;
            }
            else if (e[i]=='/'||n==3)
            {
                reply = rational.divide(rational1).toString();
            }
        }
        return  reply;
    }
    }
    
    服务器
    package com.company;
    
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;
    /**
     * Created by besti on 2019/9/29.
     */
    public class Server1823 {
        public static void main(String[] args) throws IOException, ScriptException {
            //1.建立一个服务器Socket(ServerSocket)绑定指定端口
            ServerSocket serverSocket=new ServerSocket(8800);
            //2.使用accept()方法阻止等待监听,获得新连接
            Socket socket=serverSocket.accept();
            //3.获得输入流
            InputStream inputStream=socket.getInputStream();
            BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(inputStream));
            //获得输出流
            OutputStream outputStream=socket.getOutputStream();
            PrintWriter printWriter=new PrintWriter(outputStream);
            //4.读取用户输入信息
            String info=null;
            System.out.println("服务器已经建立......");
            info = bufferedReader.readLine();
            System.out.println("我是服务器,用户信息为:" + info);
            String reply = "";
            script s = new script(info);
            reply = s.getresult();
            printWriter.write(reply);
            printWriter.flush();
    
            //5.关闭资源
            printWriter.close();
            outputStream.close();
            bufferedReader.close();
            inputStream.close();
            socket.close();
            serverSocket.close();
        }
    }
    
    客户端
    package com.company;
    import java.io.*;
    import java.net.Socket;
    
    /**
     * Created by besti on 2018/6/9.
     */
    public class SocketClient {
        public static void main(String[] args) throws IOException {
            //1.建立客户端Socket连接,指定服务器位置和端口
            Socket socket = new Socket("192.168.43.229",8800);
    //        Socket socket = new Socket("172.16.43.187",8800);
    
            //2.得到socket读写流
            OutputStream outputStream = socket.getOutputStream();
            //       PrintWriter printWriter = new PrintWriter(outputStream);
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
            //输入流
            InputStream inputStream = socket.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
            //3.利用流按照一定的操作,对socket进行读写操作
            String info1 = "1/4+1/5";
    //        String info = new String(info1.getBytes("GBK"),"utf-8");
            //     printWriter.write(info);
            //     printWriter.flush();
            outputStreamWriter.write(info1);
            outputStreamWriter.flush();
            socket.shutdownOutput();
            //接收服务器的响应
            String reply = null;
            reply = bufferedReader.readLine();
            System.out.println("接收服务器的信息为:" + reply);
    
            //4.关闭资源
            bufferedReader.close();
            inputStream.close();
            outputStreamWriter.close();
            //printWriter.close();
            outputStream.close();
            socket.close();
        }
    }
    

    运行结果如图所示:

    实验五

    同实验四相同,我们编写了一个Complex类,一个hello类,前者用来计算复数,后者用来实现将用户的字符串转换成数字输入到complex中。两次实验我们都使用了slipt来对字符串进行分割。

    复数服务器
    package com.company;
    
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;
    /**
     * Created by besti on 2019/9/29.
     */
    public class ServerComplex {
        public static void main(String[] args) throws IOException, ScriptException {
            //1.建立一个服务器Socket(ServerSocket)绑定指定端口
            ServerSocket serverSocket=new ServerSocket(8800);
            //2.使用accept()方法阻止等待监听,获得新连接
            Socket socket=serverSocket.accept();
            //3.获得输入流
            InputStream inputStream=socket.getInputStream();
            BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(inputStream));
            //获得输出流
            OutputStream outputStream=socket.getOutputStream();
            PrintWriter printWriter=new PrintWriter(outputStream);
            //4.读取用户输入信息
            String info1=null;
            System.out.println("服务器已经建立......");
            info1 = bufferedReader.readLine();
            System.out.println("第一个复数为" + info1);
            String[] reply = info1.split("i");
            hello hi = new hello(reply[0]);
            hello hii = new hello(reply[1]);
            double a,b,c,d;
            a = hi.getrealpart();
            b = hi.getimagepart();
            c = hii.getrealpart();
            d = hii.getimagepart();
            char g = reply[2].charAt(0);
            Complex c1 =new Complex(a,b);
            Complex c2 =new Complex(c,d);
            String e="";
            if (g=='+')
            {
                e = c1.ComplexAdd(c2).toString();
            }
            else if(g=='-')
            {
                e = c1.ComplexSub(c2).toString();
            }
            else if(g=='*')
            {
                e = c1.ComplexMulti(c2).toString();
            }
            else if(g=='/')
            {
                e = c1.ComplexDiv(c2).toString();
            }
            printWriter.write(e);
            printWriter.flush();
    
            //5.关闭资源
            printWriter.close();
            outputStream.close();
            bufferedReader.close();
            inputStream.close();
            socket.close();
            serverSocket.close();
        }
    }
    
    复数客户端
    package com.company;
    import java.io.*;
    import java.net.Socket;
    import java.util.Scanner;
    /**
     * Created by besti on 2018/6/9.
     */
    public class SocketClient1823 {
        public static void main(String[] args) throws IOException {
            //1.建立客户端Socket连接,指定服务器位置和端口
            Socket socket = new Socket("192.168.43.174",8800);
    //        Socket socket = new Socket("172.16.43.187",8800);
    
            //2.得到socket读写流
            OutputStream outputStream = socket.getOutputStream();
            //       PrintWriter printWriter = new PrintWriter(outputStream);
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
            //输入流
            InputStream inputStream = socket.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
            //3.利用流按照一定的操作,对socket进行读写操作
            String info1 = "";
            Scanner scan = new Scanner(System.in);
            info1 = scan.nextLine();
            String info2 = "";
            info2 =scan.nextLine();
            String s = scan.next();
    //        String info = new String(info1.getBytes("GBK"),"utf-8");
            //     printWriter.write(info);
            //     printWriter.flush();
            outputStreamWriter.write(info1);
            outputStreamWriter.flush();
            outputStreamWriter.write(info2);
            outputStreamWriter.flush();
            outputStreamWriter.write(s);
            outputStreamWriter.flush();
            socket.shutdownOutput();
            //接收服务器的响应
            String reply = null;
            reply = bufferedReader.readLine();
            System.out.println("接收服务器的信息为:" + reply);
            //4.关闭资源
            bufferedReader.close();
            inputStream.close();
            outputStreamWriter.close();
            //printWriter.close();
            outputStream.close();
            socket.close();
        }
    }
    
    package com.company;
    
    import static java.lang.Character.*;
    
    public class hello
    {
    
        private int i=0;
        private double n=0;
        private int[] a = new int[2];
        private String x;
        public hello(String s)
        {
            x = s;
        }
    
           public double getrealpart()
           {
               String[] reply = x.split("\+|-|i");
               n = Integer.parseInt(reply[0]);
               return n;
           }
           public double getimagepart()
           {
               String[] reply1 = x.split("\+|-|i");
               n = Integer.parseInt(reply1[1]);
                       return n;
           }
    
    }
    
    package com.company;
    
    public class Complex{
        private double r;
        private double i;
    
        public Complex(double R, double I) {
            r = R;
            i = I;
        }
    
        public static double getRealPart(double r) {
            return r;
        }
    
        public static double getImagePart(double i) {
            return i;
        }
    
        public Complex ComplexAdd(Complex c) {
            return new Complex(r + c.r, i + c.i);
        }
        public Complex ComplexSub(Complex c) {
            return new Complex(r - c.r, i - c.i);
        }
        public Complex ComplexMulti(Complex c) {
            return new Complex(r * c.r - i * c.i, r * c.i + i * c.r);
        }
        public Complex ComplexDiv(Complex c) {
            return new Complex((r * c.i + i * c.r)/(c.i * c.i + c.r * c.r), (i * c.i + r * c.r)/(c.i * c.i + c.r * c.r));
        }
    
        public String toString() {
            String s = " ";
            if (i > 0)
                s =  r + "+" + i + "i";
            if (i == 0)
                s =  r + "";
            if (i < 0)
                s = r + " " + i + "i";
            return s;
        }
    }
    

    运行结果如图所示:

    3. 实验过程中遇到的问题和解决过程

    • 问题1:出现connect reset问题。

    • 问题1解决方法:一开始连接不上的时候我们查阅了百度,可是发现始终没有有效的解决方法,于是我决定把编写的类给去掉,检查连接是否有问题。

    图片显示在没有类的情况下(里面的类是后面加上去的),并没有出现connect reset的问题,所以应该是类出现了问题。
    那么我编写了一个主程序aswd来运行试试看类,(因时间仓促没有截图)在运行过程中可以发现类里面的问题,并及时纠正,这样有助于快速找出程序问题的原因。

    (如图,我利用这个程序把自己写过的四个类都测试过,以此来找出程序中存在的问题)。

    • 问题2:split的使用问题
    • 问题2解决方法;split(“”)是将一个字符串一“”里的字符为标准,分成多个部分,如
    String s = "jdwlkaj-dwjakjwd";
    String[] a = s.split("-"); 
    

    那么,a[0]="jdwlkaj",a[1]="dwjakjwd",但是当我们在“”里放入+号时,系统却显示错误?原来+ * 不是有效的模式匹配规则表达式,用"" "+"转义后即可得到正确的结果。只需要改为split(“|+”)程序就可以运行了。

    其他(感悟、思考等)

    • 本次实验看起来对我们难度非常的大,其实内在是很简单明了的,有理数类的加减乘除和复数类的加减乘除的代码书上其实都有,而我们只需要理解清楚javasocket编程代码上的含义还有明白如何运用类将字符串转换成数字就好了,造成这次实验完成的不好在于对于书本的不重视。
    • 当程序运行出错的时候,其实可以将idea下方报错的名字信息复制粘贴到百度上来查询是为什么错了,这有利于我们自己发现问题,而不是有一点的问题都去询问助教。

    参考资料

    《Java程序设计与数据结构教程(第二版)》

    《Java程序设计与数据结构教程(第二版)》学习指导

  • 相关阅读:
    ubuntu-18.04自动配置脚本
    Nodejs on windows 10
    终端接收FFMEPG推送的流出现音频卡顿问题
    FFMPEG 4.0 版本 支持PSI设置
    FFMPEG 支持https协议
    FFmpeg修改AC3编码的描述子
    FFMPEG 设置socket缓冲区
    将 h264 格式转换为YUV数据
    将 YUV 数据 编码为 h.264 格式
    将 PCM 数据编码为AAC格式
  • 原文地址:https://www.cnblogs.com/yangkaihan/p/11631458.html
Copyright © 2011-2022 走看看