博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2017-2018-2 20165226 实验五《网络编程与安全》实验报告
阅读量:6314 次
发布时间:2019-06-22

本文共 14728 字,大约阅读时间需要 49 分钟。

实验五《网络编程与安全》

实验目的

  • 一、结对实现中缀表达式转后缀表达式的功能 ,从上面功能中获取的表达式中实现后缀表达式求值的功能

  • 二、 基于Java Socket实现客户端/服务器功能,传输方式用TCP,客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式通过网络发送给服务器

  • 三、服务器接收到后缀表达式表达式后,进行解密(和客户端协商密钥,可以用数组保存),然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端

  • 四、客户端和服务器用DH算法进行3DES或AES算法的密钥交换

  • 五、客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文发送给服务器

实验内容及步骤

(一)结对实现中缀表达式转后缀表达式的功能 ,从上面功能中获取的表达式中实现后缀表达式求值的功能

1、设置IP地址

  • 通过输入ipconfig指令来查询IP地址
    1047870-20180527120221069-1921235474.png

2、结对实现中缀表达式转后缀表达式的功能 MyBC.java,进行测试

1047870-20180522212726482-595927508.png

3、 结对实现从上面功能中获取的表达式中实现后缀表达式求值的功能,调用MyDC.java

1047870-20180522212714540-1708410677.png

1047870-20180522212656104-1737339910.png

4、知识点

  • 中缀式转化后缀式
    • 设立一个栈,存放运算符,首先栈为空;
    • 从左到右扫描中缀式,若遇到操作数,直接输出,并输出一个空格作为两个操作数的分隔符;
    • 若遇到运算符,则与栈顶比较,比栈顶级别高则进栈,否则退出栈顶元素并输出,然后输出一个空格作分隔符;
    • 若遇到左括号,进栈;若遇到右括号,则一直退栈输出,直到退到左括号止。
      当栈变成空时,输出的结果即为后缀表达式。
  • 算符优先法求解表达式
    • 建立符号运算的优先级关系表

      1047870-20180522213424256-284280487.png

    • 设操作栈OPND、运算符栈OPTR,最低符号#压进OPTR
    • 读入字符C,C若是操作数, 进OPND;若是运算符,与OPTR栈顶元素(A)比较,根据算符优先级,决定如何处理:
      • A<C, C压入OPTR栈;
      • A=C, A从OPTR出栈;
      • A>C,A出栈,从OPND依次弹出两个操作数y、x, 计算Z=x A y,Z压入OPND栈。C压进OPTR.
    • 重复上步操作直至表达式结果

(二)结对编程

基于Java Socket实现客户端/服务器功能,传输方式用TCP,客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式通过网络发送给服务器;服务器接收到后缀表达式,调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端; 客户端显示服务器发送过来的结果
  • Client
/***Created by xiang on 2018/5/23.*/import java.io.BufferedReader;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.net.Socket;public class Client {  public static final String IP_ADDR = "127.0.0.1";//服务器地址    public static final int PORT = 12345;//服务器端口号    public static void main(String[] args) {        System.out.println("客户端启动...");        System.out.println("当接收到服务器端字符为 \"OK\" 的时候, 客户端将终止\n");        while (true) {            Socket socket = null;            try {                //创建一个流套接字并将其连接到指定主机上的指定端口号                socket = new Socket(IP_ADDR, PORT);                //读取服务器端数据                DataInputStream input = new DataInputStream(socket.getInputStream());                //向服务器端发送数据                DataOutputStream out = new DataOutputStream(socket.getOutputStream());                System.out.print("请输入: \t");                String str = new BufferedReader(new InputStreamReader(System.in)).readLine();                MyBC turner = new MyBC();                String str1 = turner.turn(str);                int length=0,i=0;                while(str1.charAt(i)!='\0'){                    length++;                    i++;                }                String str2 = str1.substring(1,length-1);                out.writeUTF(str2);                String ret = input.readUTF();                System.out.println("服务器端返回过来的是: " + ret);                /*if ("OK".equals(ret)) {                    System.out.println("客户端将关闭连接");                    Thread.sleep(500);                    break;                }*/                out.close();                input.close();            } catch (Exception e) {                System.out.println("客户端异常:" + e.getMessage());            } finally {                if (socket != null) {                    try {                        socket.close();                    } catch (IOException e) {                        socket = null;                        System.out.println("客户端 finally 异常:" + e.getMessage());                    }                }            }        }    }}
  • 测试结果
    1047870-20180527120234227-1495059245.png

(三)加密结对编程

  1. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
  2. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密后通过网络把密文发送给服务器
  3. 服务器接收到后缀表达式表达式后,进行解密(和客户端协商密钥,可以用数组保存),然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
  4. 客户端显示服务器发送过来的结果
  • client3
/***Created by xiang on 2018/5/24.*/import java.io.BufferedReader;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.net.Socket;public class Client2 {    public static final String IP_ADDR = "127.0.0.1";//服务器地址    public static final int PORT = 1234;//服务器端口号    public static void main(String[] args) {        System.out.println("客户端启动...");        System.out.println("当接收到服务器端字符为 \"OK\" 的时候, 客户端将终止\n");        while (true) {            Socket socket = null;            try {                //创建一个流套接字并将其连接到指定主机上的指定端口号                socket = new Socket(IP_ADDR, PORT);                //读取服务器端数据                DataInputStream input = new DataInputStream(socket.getInputStream());                //向服务器端发送数据                DataOutputStream out = new DataOutputStream(socket.getOutputStream());                System.out.print("请输入: \t");                String str = new BufferedReader(new InputStreamReader(System.in)).readLine();                MyBC turner = new MyBC();                Skey_DES skey_des = new Skey_DES();                skey_des.key_DES();                Skey_kb skey_kb = new Skey_kb();                skey_kb.key();        /*产生密钥*/                SEnc sEnc = new SEnc();                String str1 = turner.turn(str);                int length=0,i=0;                while(str1.charAt(i)!='\0'){                    length++;                    i++;                }                String str2 = str1.substring(1,length-1);                out.writeUTF(str2);                String ret = input.readUTF();                System.out.println("服务器端返回过来的是: " + ret);                // 如接收到 "OK" 则断开连接                /*if ("OK".equals(ret)) {                    System.out.println("客户端将关闭连接");                    Thread.sleep(500);                    break;                }*/                out.close();                input.close();            } catch (Exception e) {                System.out.println("客户端异常:" + e.getMessage());            } finally {                if (socket != null) {                    try {                        socket.close();                    } catch (IOException e) {                        socket = null;                        System.out.println("客户端 finally 异常:" + e.getMessage());                    }                }            }        }    }}
  • SEnc
/***Created by xiang on 2018/5/24.*/import java.io.*;import java.security.*;import javax.crypto.*;public class SEnc{    static String s;    public SEnc(String s){        this.s = s;    }    public void  encrypt(){        try{        FileInputStream f=new FileInputStream("key1.dat");        ObjectInputStream b=new ObjectInputStream(f);        Key k=(Key)b.readObject( );        Cipher cp=Cipher.getInstance("DESede");        cp.init(Cipher.ENCRYPT_MODE, k);        byte ptext[]=s.getBytes("UTF8");        for(int i=0;i
  • 结果
    1047870-20180528164503693-62958886.png

(四)密钥分发结对编程

  1. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
  2. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文发送给服务器
  3. 客户端和服务器用DH算法进行3DES或AES算法的密钥交换
  4. 服务器接收到后缀表达式表达式后,进行解密,然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
  5. 客户端显示服务器发送过来的结果
  • Client4
/***Created by xiang on 2018/5/26.*/import java.io.*;import java.net.Socket;public class Client4 {    public static void main(String[] args) {        Socket s = null;        try {            s = new Socket("172.30.0.159", 4004);        }catch (IOException e) {            System.out.println("未连接到服务器");        }    try    {        DataInputStream input = new DataInputStream(s.getInputStream());        System.out.print("请输入: \t");        String str = new BufferedReader(new InputStreamReader(System.in)).readLine();        MyBC turner = new MyBC();        String str1 = turner.turn(str);        int length = 0, i = 0;        while (str1.charAt(i) != '\0') {            length++;            i++;        }        String str2 = str1.substring(1, length - 1);        SEnc senc = new SEnc(str2);//指定后缀表达式为明文字符串        senc.encrypt();//加密    }catch(Exception e) {        System.out.println("客户端异常:" + e.getMessage());    }        File sendfile = new File("SEnc.dat");        File sendfile1 = new File("Keykb1.dat");        /**定义文件输入流,用来打开、读取即将要发送的文件*/        FileInputStream fis = null;        FileInputStream fis1 = null;        /**定义byte数组来作为数据包的存储数据包*/        byte[] buffer = new byte[4096 * 5];        byte[] buffer1 = new byte[4096 * 5];        /**定义输出流,使用socket的outputStream对数据包进行输出*/        OutputStream os = null;        if(!sendfile.exists() || !sendfile1.exists()){            System.out.println("客户端:要发送的文件不存在");            return;        }        try {            fis = new FileInputStream(sendfile);            fis1 = new FileInputStream(sendfile1);        } catch (FileNotFoundException e1) {            e1.printStackTrace();        }        try {            PrintStream ps = new PrintStream(s.getOutputStream());            ps.println("111/#" + sendfile.getName() + "/#" + fis.available());            ps.flush();        } catch (IOException e) {            System.out.println("服务器连接中断");        }        try {            Thread.sleep(2000);        } catch (InterruptedException e1) {            e1.printStackTrace();        }传输的关键代码        try {            /**获取socket的OutputStream,以便向其中写入数据包*/            os = s.getOutputStream();            /** size 用来记录每次读取文件的大小*/            int size = 0;            /**使用while循环读取文件,直到文件读取结束*/            while((size = fis.read(buffer)) != -1){                System.out.println("客户端发送数据包,大小为" + size);                /**向输出流中写入刚刚读到的数据包*/                os.write(buffer, 0, size);                /**刷新一下*/                os.flush();            }        } catch (FileNotFoundException e) {            System.out.println("客户端读取文件出错");        } catch (IOException e) {            System.out.println("客户端输出文件出错");        }finally{            try {                if(fis != null)                    fis.close();            } catch (IOException e) {                System.out.println("客户端文件关闭出错");            }//catch (IOException e)        }//finally        try {            PrintStream ps1 = new PrintStream(s.getOutputStream());            ps1.println("111/#" + sendfile1.getName() + "/#" + fis1.available());            ps1.flush();        } catch (IOException e) {            System.out.println("服务器连接中断");        }        try {            Thread.sleep(2000);        } catch (InterruptedException e1) {            e1.printStackTrace();        }        try {            /**获取socket的OutputStream,以便向其中写入数据包*/            os = s.getOutputStream();            /** size 用来记录每次读取文件的大小*/            int size = 0;            /**使用while循环读取文件,直到文件读取结束*/            while((size = fis1.read(buffer1)) != -1){                System.out.println("客户端发送数据包,大小为" + size);                /**向输出流中写入刚刚读到的数据包*/                os.write(buffer1, 0, size);                /**刷新一下*/                os.flush();            }        } catch (FileNotFoundException e) {            System.out.println("客户端读取文件出错");        } catch (IOException e) {            System.out.println("客户端输出文件出错");        }finally{            try {                if(fis1 != null)                    fis1.close();            } catch (IOException e) {                System.out.println("客户端文件关闭出错");            }//catch (IOException e)        }//finally        try{            DataInputStream input = new DataInputStream(s.getInputStream());            String ret = input.readUTF();            System.out.println("服务器端返回过来的是: " + ret);        } catch (Exception e) {            e.printStackTrace();        }finally {            if (s != null) {                try {                    s.close();                } catch (IOException e) {                    s = null;                    System.out.println("客户端 finally 异常:" + e.getMessage());                }            }        }    }//public static void main(String[] args)}//public class ClientSend
  • 结果
    1047870-20180527120724051-655832912.png

(五)密钥分发结对编程

  1. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
  2. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文发送给服务器
  3. 客户端和服务器用DH算法进行3DES或AES算法的密钥交换
  4. 服务器接收到后缀表达式表达式后,进行解密,然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
  5. 客户端显示服务器发送过来的结果
  • Client5
import java.io.*;import java.net.*;import java.security.MessageDigest;public class Client5 {    public static void main(String args[]) throws Exception {        MyBC turner = new MyBC();        Skey_DES skey_des = new Skey_DES();        skey_des.key_DES();        Skey_kb skey_kb = new Skey_kb();        skey_kb.key();        /*产生密钥*/        SEnc sEnc = new SEnc();        try {            Socket socket = new Socket("127.0.0.1", 4700);//向本机的4700端口发出客户请求            BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));//由系统标准输入设备构造BufferedReader对象            PrintWriter os = new PrintWriter(socket.getOutputStream());//由Socket对象得到输出流,并构造PrintWriter对象            BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream()));//由Socket对象得到输入流,并构造相应的BufferedReader对象            String readline;            readline =sin.readLine();            //从系统标准输入读入一字符串            String x = readline;            // 将客户端明文的Hash值传送给服务器            MessageDigest m2 = MessageDigest.getInstance("MD5");            m2.update(x.getBytes());            byte a[] = m2.digest();            String result = "";            for (int i = 0; i < a.length; i++) {                result += Integer.toHexString((0x000000ff & a[i]) | 0xffffff00).substring(6);            }            System.out.println("明文MD5值为:" + result);            os.println(result);//通过网络将明文的Hash函数值传送到服务器            // String str = is.readLine();// 从网络输入流读取结果            System.out.println("从服务器接收到的结果为:" + result); // 输出服务器返回的结果            while (!readline.equals("bye")) {//若从标准输入读入的字符串为 "bye"则停止循环                readline = SEnc.Enc(turner.turn(readline));                os.println(readline);                /*把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES加密后通过网络发送给服务器*/                //将从系统标准输入读入的字符串输出到Server                os.flush();                //刷新输出流,使Server马上收到该字符串                System.out.println("Client:" + readline);                //在系统标准输出上打印读入的字符串                System.out.println("Server:" + is.readLine());                //从Server读入一字符串,并打印到标准输出上                readline = sin.readLine(); //从系统标准输入读入一字符串            } //继续循环            os.close(); //关闭Socket输出流            is.close(); //关闭Socket输入流            socket.close(); //关闭Socket        } catch (Exception e) {            System.out.println("Error" + e); //出错,则打印出错信息        }    }}
  • 结果
    1047870-20180528165305286-319944840.png

遇到问题及解决方案

  • 问题1:无法进行测试

    1047870-20180522212634249-683253222.png

  • 问题1解决方案:测试前应填入数据,再进行测试
  • 问题2:进行测试时,报错input exception reported

    1047870-20180522212624059-1388038190.png

  • 问题2解决方案:搜了一下,发现是格式的问题,字符间应有空格相连接

    1047870-20180522212612740-383307923.png

  • 问题3:出现java.net.SocketException: Connection reset,客户端输出文件出错

    1047870-20180524195320023-1480912904.png
    1047870-20180527121347242-466281965.png

  • 问题3解决方案:该异常在客户端和服务器端均有可能发生,引起该异常的原因有两个,第一个就是如果一端的Socket被关闭(或主动关闭或者因为异常退出而引起的关闭),另一端仍发送数据,发送的第一个数据包引发该异常(Connect reset by peer)。另一个是一端退出,但退出时并未关闭该连接,另一端如果在从连接中读数据则抛出该异常(Connection reset)。简单的说就是在连接断开后的读和写操作引起的。 在读取信息时不应该关闭客户端。

  • 问题4:无法运行程序,报错

    1047870-20180527122007064-112556009.png

  • 问题4解决方案:重新启动,或者换个端口,比如之前是4004,就可以换成1234

统计PSP(Personal Software Process)时间:

步骤 耗时(h) 百分比
设计 2 20%
代码实现 5 50%
测试 2 20%
分析总结 1 10%

实验小结

本次实验过程中出现了很多问题,反反复复折腾了一周,不过在不断地从书中网上查询解决问题的过程中,收获颇丰。其实不管是学习生活还是今后工作,有时候需要适当地逼一下自己,可能在某一方面投入90%精力但仍不见希望时,我们需要做的可能就是再努力10%。这应该是本学期最后一次实验了,虽然Java实验真的磨人,不过不论从知识的提升还是耐力的磨练,总算是有所收获,还是挺感谢娄老师。希望自己以后也能屏住最后一口气,撑住往前走。

转载于:https://www.cnblogs.com/musea/p/9074269.html

你可能感兴趣的文章
POJ 2312Battle City(BFS-priority_queue 或者是建图spfa)
查看>>
CentOS 7 巨大变动之 firewalld 取代 iptables
查看>>
延时任务和定时任务
查看>>
linux下的权限问题
查看>>
教你如何使用Flutter和原生App混合开发
查看>>
Spring Boot 整合redis
查看>>
CSS hover改变背景图片过渡动画生硬
查看>>
淘宝应对"双11"的技术架构分析
查看>>
订单的子单表格设置颜色
查看>>
Office365 Exchange Hybrid 番外篇 ADFS后端SQL群集(一)
查看>>
9个offer,12家公司,35场面试,从微软到谷歌,应届计算机毕业生的2012求职之路...
查看>>
lvs fullnat部署手册(三)rs内核加载toa篇
查看>>
C++策略模式
查看>>
我的友情链接
查看>>
oracle表分区详解
查看>>
网络编程中常见结构体
查看>>
SSL/TLS原理详解
查看>>
Docker 自定义SSH服务镜像
查看>>
JavaScript强化教程 —— Cocos2d-JS自动JSB绑定规则修改
查看>>
configure: error: in `/root/httpd-2.2.11/srclib/apr': c
查看>>