20155215 宣言 实验五 网络编程与安全 实验报告

实验要求

1.没有Linux基础的同学建议先学习《Linux基础入门(新版)》《Vim编辑器》 课程;

2.完成实验、撰写实验报告,实验报告模板见QQ群,注意实验报告重点是运行结果,遇到的问题(工具查找,安装,使用,程序的编辑,调试,运行等)、解决办法(空洞的方法如“查网络”、“问同学”、“看书”等一律得0分)以及分析(从中可以得到什么启示,有什么收获,教训等);

3.实验报告中统计自己的PSP(Personal Software Process)时间:

步骤 耗时 百分比
需求分析
设计
代码实现
测试
分析总结

实验内容

一、两人一组结对编程:

  1. 参考http://www.cnblogs.com/rocedu/p/6766748.html#SECDSA
  2. 结对实现中缀表达式转后缀表达式的功能 MyBC.java
  3. 结对实现从上面功能中获取的表达式中实现后缀表达式求值的功能,调用MyDC.java
  4. 上传测试代码运行结果截图和码云链接

这题一共有三个代码,比起后面的四道题,这题还是较为简单的。
MyBC.java的代码如下所示:

/**
 * Created by XY on 2017/6/1.
 */

import java.util.Iterator;
import java.util.LinkedList;

public class MyBC {
    private static LinkedList<String> op1 = new LinkedList<>();
    private static LinkedList<String> op2 = new LinkedList<>();
    private static StringBuilder a = new StringBuilder();

    public StringBuilder houzhui(LinkedList<String> list) {
        Iterator<String> i = list.iterator();
        while (i.hasNext()) {
            String s = i.next();
            if (isOperator(s)) {
                if (op1.isEmpty()) {
                    op1.push(s);
                } else {
                    if (priority(op1.peek()) <= priority(s) && !s.equals(")")) {
                        op1.push(s);
                    } else if (!s.equals(")") && priority(op1.peek()) > priority(s)) {
                        while (op1.size() != 0 && priority(op1.peek()) >= priority(s)
                                && !op1.peek().equals("(")) {
                            if (!op1.peek().equals("(")) {
                                String operator = op1.pop();
                                a.append(operator).append(" ");
                                op2.push(operator);
                            }
                        }
                        op1.push(s);
                    } else if (s.equals(")")) {
                        while (!op1.peek().equals("(")) {
                            String operator = op1.pop();
                            a.append(operator).append(" ");
                            op2.push(operator);
                        }
                        op1.pop();
                    }
                }
            } else {
                a.append(s).append(" ");
                op2.push(s);
            }
        }
        if (!op1.isEmpty()) {
            Iterator<String> iterator = op1.iterator();
            while (iterator.hasNext()) {
                String operator = iterator.next();
                a.append(operator).append(" ");
                op2.push(operator);
                iterator.remove();
            }
        }
        return a;
    }

    private static boolean isOperator(String oper) {
        if (oper.equals("+") || oper.equals("-") || oper.equals("/") || oper.equals("*")
                || oper.equals("(") || oper.equals(")")) {
            return true;
        }
        return false;
    }

    private static int priority(String s) {
        switch (s) {
            case "+":
                return 1;
            case "-":
                return 1;
            case "*":
                return 2;
            case "/":
                return 2;
            case "(":
                return 3;
            case ")":
                return 3;
            default:
                return 0;
        }
    }
}


MyBCTest.java的代码如下:

/**
 * Created by XY on 2017/6/1.
 */

import java.util.Iterator;
import java.util.LinkedList;

public class MyBC {
    private static LinkedList<String> op1 = new LinkedList<>();
    private static LinkedList<String> op2 = new LinkedList<>();
    private static StringBuilder a = new StringBuilder();

    public StringBuilder houzhui(LinkedList<String> list) {
        Iterator<String> i = list.iterator();
        while (i.hasNext()) {
            String s = i.next();
            if (isOperator(s)) {
                if (op1.isEmpty()) {
                    op1.push(s);
                } else {
                    if (priority(op1.peek()) <= priority(s) && !s.equals(")")) {
                        op1.push(s);
                    } else if (!s.equals(")") && priority(op1.peek()) > priority(s)) {
                        while (op1.size() != 0 && priority(op1.peek()) >= priority(s)
                                && !op1.peek().equals("(")) {
                            if (!op1.peek().equals("(")) {
                                String operator = op1.pop();
                                a.append(operator).append(" ");
                                op2.push(operator);
                            }
                        }
                        op1.push(s);
                    } else if (s.equals(")")) {
                        while (!op1.peek().equals("(")) {
                            String operator = op1.pop();
                            a.append(operator).append(" ");
                            op2.push(operator);
                        }
                        op1.pop();
                    }
                }
            } else {
                a.append(s).append(" ");
                op2.push(s);
            }
        }
        if (!op1.isEmpty()) {
            Iterator<String> iterator = op1.iterator();
            while (iterator.hasNext()) {
                String operator = iterator.next();
                a.append(operator).append(" ");
                op2.push(operator);
                iterator.remove();
            }
        }
        return a;
    }

    private static boolean isOperator(String oper) {
        if (oper.equals("+") || oper.equals("-") || oper.equals("/") || oper.equals("*")
                || oper.equals("(") || oper.equals(")")) {
            return true;
        }
        return false;
    }

    private static int priority(String s) {
        switch (s) {
            case "+":
                return 1;
            case "-":
                return 1;
            case "*":
                return 2;
            case "/":
                return 2;
            case "(":
                return 3;
            case ")":
                return 3;
            default:
                return 0;
        }
    }
}


MyDC的代码如下:

/**
 * Created by XY on 2017/6/1.
 */

import java.util.LinkedList;



public class MyDC {
    public static int evaluate(StringBuilder b) {
        LinkedList<String> mList = new LinkedList<>();
        String[] postStr = b.toString().split(" ");
        int result;
        for (String s : postStr) {
            if (fuhao(s)) {
                if (!mList.isEmpty()) {
                    int num1 = Integer.valueOf(mList.pop());
                    int num2 = Integer.valueOf(mList.pop());
                    if (s.equals("/") && num1 == 0) {
                        System.out.println("除数不能为0");
                        return 0;
                    }
                    int newNum = cal(num2, num1, s);
                    mList.push(String.valueOf(newNum));
                }
            } else {
                mList.push(s);
            }
        }
        //if (!mList.isEmpty()) {
        //System.out.println("result: "+mList.pop());
      result=Integer.parseInt(mList.pop());
        // }


        return result;
    }

    private static boolean fuhao(String a) {
        if (a.equals("+") || a.equals("-") || a.equals("/") || a.equals("*")
                || a.equals("(") || a.equals(")")) {
            return true;
        }
        return false;
    }
    /*private static int priority(String s) {

        switch (s) {
            case "+":
               return 1;
            case "-":
              return 1;
         case "*":

                return 2;

            case "/":

                return 2;

            case "(":
              return 3;
           case ")":
             return 3;
            default:
              return 0;

        }
    }*/

    private static int cal(int num1, int num2, String operator) {
        switch (operator) {
            case "+":
                return num1 + num2;
            case "-":
                return num1 - num2;
            case "*":
                return num1 * num2;
            case "/":
                return num1 / num2;
            default:
                return 0;
        }
    }
}

    /*private boolean isOperator(String token) {



        return (token.equals("+") || token.equals("-") ||
        token.equals("*") || token.equals("/"));

    }

   /* private int evalSingleOp(char operation, int op1, int op2) {

        int result = 0;
        switch (operation) {
           case ADD:
             result = op1 + op2;
               break;
            case SUBTRACT:
             result = op1 - op2;

                break;
          case MULTIPLY:
               result = op1 * op2;
             break;

            case DIVIDE:
                result = op1 / op2;
        }
       return result;

    }*/

最后的运行结果如下图所示:

二、结对编程:1人负责客户端,一人负责服务器

  1. 注意责任归宿,要会通过测试证明自己没有问题
  2. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
  3. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式通过网络发送给服务器
  4. 服务器接收到后缀表达式,调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
  5. 客户端显示服务器发送过来的结果
  6. 上传测试结果截图和码云链接

服务器的代码如下:

/**
 * Created by XY on 2017/6/2.
 */
import java.io.*;
import java.net.*;

import static java.lang.Integer.*;

public class fuwuqi {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        Socket socket = null;
        OutputStream os = null;
        InputStream is = null;
        //监听端口号
        int port = 10000;
        try {
            //建立连接
            serverSocket = new ServerSocket(port);
            System.out.println("建立连接成功!");
            //获得连接
            socket = serverSocket.accept();
            System.out.println("获得连接成功!");
            //接收客户端发送内容
            is = socket.getInputStream();
            byte[] b = new byte[1024];
            int n = is.read(b);
            System.out.println("接收数据成功!");
            //输出
            String message=new String(b,0,n);
            System.out.println("来自客户端的数据内容为:" + message);
            String result=code06011.dealEquation(message);
            //向客户端发送反馈内容
            //os = socket.getOutputStream();
            //os.write(b,0,n);
            os = socket.getOutputStream();
            os.write(result.getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try{
                //关闭流和连接
                os.close();
                is.close();
                socket.close();
                serverSocket.close();
            }catch(Exception e){}
        }
    }
}


客户端的代码如下

/**
 * Created by XY on 2017/6/2.
 */
import java.io.*;
import java.net.*;
public class kehuduan {
    public static void main(String[] args) {
        Socket socket = null;
        InputStream is = null;
        OutputStream os = null;
        //服务器端IP地址
        String serverIP = "10.43.32.95";
        //服务器端端口号
        int port = 10000;
        //发送内容
        System.out.println("输入中缀表达式:(1+2)*3/4");
        String data = code06011.toSuffix("(1+2)*3/4");
        System.out.println("转换后缀表达式:"+data);

        try {
            //建立连接
            socket = new Socket(serverIP, port);
            System.out.println("建立连接成功!");
            //发送数据
            os = socket.getOutputStream();
            os.write(data.getBytes());
            System.out.println("发送数据成功!");
            //接收数据
            is = socket.getInputStream();
            byte[] b = new byte[1024];
            int n = is.read(b);
            System.out.println("接收数据成功!");
            //输出反馈数据
            System.out.println("来自服务器的数据内容为:" + new String(b, 0, n));
        } catch (Exception e) {
            e.printStackTrace(); //打印异常信息
        } finally {
            try {
                //关闭流和连接
                is.close();
                os.close();
                socket.close();
            } catch (Exception e2) {
            }
        }
    }
}

三、加密结对编程:1人负责客户端,一人负责服务器

  1. 注意责任归宿,要会通过测试证明自己没有问题
  2. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
  3. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密后通过网络把密文发送给服务器
  4. 服务器接收到后缀表达式表达式后,进行解密(和客户端协商密钥,可以用数组保存),然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
  5. 客户端显示服务器发送过来的结果
  6. 上传测试结果截图和码云链接

这题一共有三个代码
ComputeTCPServer代码如下:

/**
 * Created by XY on 2017/6/1.
 */
import java.net.*;
import java.io.*;
import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import javax.crypto.interfaces.*;
import java.security.interfaces.*;
import java.math.*;
public class ComputeTCPServer{
    public static void main(String srgs[]) throws Exception
    {
        ServerSocket sc = null;
        Socket socket=null;
        try
        {
            sc= new ServerSocket(9999);//创建服务器套接字
            System.out.println("端口号:" + sc.getLocalPort());
            System.out.println("服务器已经启动...");
            socket = sc.accept();   //等待客户端连接
            System.out.println("已经建立连接");//获得网络输入流对象的引用
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));//获得网络输出流对象的引用
            PrintWriter out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);

            //使用服务器端RSA的私钥对DES的密钥进行解密
            String aline2=in.readLine();
            BigInteger c=new BigInteger(aline2);
            FileInputStream f=new FileInputStream("Skey_RSA_priv.dat");
            ObjectInputStream b=new ObjectInputStream(f);
            RSAPrivateKey prk=(RSAPrivateKey)b.readObject( );

            BigInteger d=prk.getPrivateExponent();
            BigInteger n=prk.getModulus();
            BigInteger m=c.modPow(d,n);
            byte[] keykb=m.toByteArray();

            //使用DES对密文进行解密
            String aline=in.readLine();//读取客户端传送来的数据
            byte[] ctext=parseHexStr2Byte(aline);
            Key k=new  SecretKeySpec(keykb,"DESede");
            Cipher cp=Cipher.getInstance("DESede");
            cp.init(Cipher.DECRYPT_MODE, k);
            byte []ptext=cp.doFinal(ctext);
            String p=new String(ptext,"UTF8");
            System.out.println("从客户端接收到信息为:"+p); //通过网络输出流返回结果给客户端

            //验证明文的准确性
            String aline3=in.readLine();
            String x=p;
            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(result);

            if(aline3.equals(result))
            {
                System.out.println("匹配成功");
            }

            out.println("匹配成功");
            out.close();
            in.close();
            sc.close();
        } catch (Exception e) {
            System.out.println(e);
        }
    }
    public static byte[] parseHexStr2Byte(String hexStr)
    {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length()/2];
        for (int i = 0;i< hexStr.length()/2; i++)
        {
            int high = Integer.parseInt(hexStr.substring(i*2, i*2+1 ), 16);
            int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }
    public static String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++)
        {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1)
            {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

}

SocketService的代码如下:

/**
 * Created by XY on 2017/6/1.
 */
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketService {
    //搭建服务器端
    public static void main(String[] args) throws IOException{
        SocketService socketService = new SocketService();
        //1、a)创建一个服务器端Socket,即SocketService
        socketService.oneServer();
    }
    public  void oneServer(){
        try{
            ServerSocket server=null;
            try{
                server=new ServerSocket(9999);
                //b)指定绑定的端口,并监听此端口。
                System.out.println("服务器启动成功");
                //创建一个ServerSocket在端口5200监听客户请求
            }catch(Exception e) {
                System.out.println("没有启动监听:"+e);
                //出错,打印出错信息
            }
            Socket socket=null;
            try{
                socket=server.accept();
                //2、调用accept()方法开始监听,等待客户端的连接
                //使用accept()阻塞等待客户请求,有客户
                //请求到来则产生一个Socket对象,并继续执行
            }catch(Exception e) {
                System.out.println("Error."+e);
                //出错,打印出错信息
            }
            //3、获取输入流,并读取客户端信息
            String line;
            BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
            //由Socket对象得到输入流,并构造相应的BufferedReader对象
            PrintWriter writer=new PrintWriter(socket.getOutputStream());
            //由Socket对象得到输出流,并构造PrintWriter对象
            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
            //由系统标准输入设备构造BufferedReader对象
            System.out.println("Client:"+in.readLine());
            //在标准输出上打印从客户端读入的字符串
            line=br.readLine();
            //从标准输入读入一字符串
            //4、获取输出流,响应客户端的请求
            while(!line.equals("end")){
                //如果该字符串为"end",则停止循环
                writer.println(line);
                //向客户端输出该字符串
                writer.flush();
                //刷新输出流,使Client马上收到该字符串
                System.out.println("Server:"+line);
                //在系统标准输出上打印读入的字符串
                System.out.println("Client:"+in.readLine());
                //从Client读入一字符串,并打印到标准输出上
                line=br.readLine();
                //从系统标准输入读入一字符串
            } //继续循环

            //5、关闭资源
            writer.close(); //关闭Socket输出流
            in.close(); //关闭Socket输入流
            socket.close(); //关闭Socket
            server.close(); //关闭ServerSocket
        }catch(Exception e) {//出错,打印出错信息
            System.out.println("Error."+e);
        }
    }
}

StockCline的代码如下:

/**
 * Created by XY on 2017/6/1.
 */
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URL;

public class StockCline{
    // 搭建客户端
    public static void main(String[] args) throws IOException {
        try {
            // 1、创建客户端Socket,指定服务器地址和端口
            // Socket socket=new Socket("127.0.0.1",5200);
            Socket socket = new Socket("127.0.0.1", 9999);
            System.out.println("客户端启动成功");
            // 2、获取输出流,向服务器端发送信息
            // 向本机的52000端口发出客户请求
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            // 由系统标准输入设备构造BufferedReader对象
            PrintWriter write = new PrintWriter(socket.getOutputStream());
            // 由Socket对象得到输出流,并构造PrintWriter对象
            //3、获取输入流,并读取服务器端的响应信息
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            // 由Socket对象得到输入流,并构造相应的BufferedReader对象
            String readline;
            readline = br.readLine(); // 从系统标准输入读入一字符串
            while (!readline.equals("end")) {
                // 若从标准输入读入的字符串为 "end"则停止循环
                write.println(readline);
                // 将从系统标准输入读入的字符串输出到Server
                write.flush();
                // 刷新输出流,使Server马上收到该字符串
                System.out.println("Client:" + readline);
                // 在系统标准输出上打印读入的字符串
                System.out.println("Server:" + in.readLine());
                // 从Server读入一字符串,并打印到标准输出上
                readline = br.readLine(); // 从系统标准输入读入一字符串
            } // 继续循环
            //4、关闭资源
            write.close(); // 关闭Socket输出流
            in.close(); // 关闭Socket输入流
            socket.close(); // 关闭Socket
        } catch (Exception e) {
            System.out.println("can not listen to:" + e);// 出错,打印出错信息
        }
    }

}

四、密钥分发结对编程:1人负责客户端,一人负责服务器

  1. 注意责任归宿,要会通过测试证明自己没有问题
  2. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
  3. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文发送给服务器
  4. 客户端和服务器用DH算法进行3DES或AES算法的密钥交换
  5. 服务器接收到后缀表达式表达式后,进行解密,然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
  6. 客户端显示服务器发送过来的结果
  7. 上传测试结果截图和码云链接

五、完整性校验结对编程:1人负责客户端,一人负责服务器

  1. 注意责任归宿,要会通过测试证明自己没有问题
  2. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
  3. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文和明文的MD5値发送给服务器
  4. 客户端和服务器用DH算法进行3DES或AES算法的密钥交换
  5. 服务器接收到后缀表达式表达式后,进行解密,解密后计算明文的MD5值,和客户端传来的MD5进行比较,一致则调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
  6. 客户端显示服务器发送过来的结果
  7. 上传测试结果截图和码云链接
    最后两题其实和第三题类似,但是有一些小的改动,所以代码我就不重复贴了,下面是我的运行截图:

实验感想

这次实验我觉得难度真的很大,我和我的结对对象20155232花了整整一周来做这个实验。我们在网上查了很多资料,然后请教同学,最后才赶在最后期限做完的,感觉自己不会的还有很多,还需要加油。

PSP时间

步骤 耗时 百分比
需求分析 30 7.5%
设计 50 12.5%
代码实现 240 60%
测试 60 15%
分析总结 20 5%
原文地址:https://www.cnblogs.com/xuanyan/p/6937205.html