20155215 宣言 實驗五 網絡編程與安全 實驗報告

實驗要求

1.沒有Linux基礎的同窗建議先學習《Linux基礎入門(新版)》《Vim編輯器》 課程;html

2.完成實驗、撰寫實驗報告,實驗報告模板見QQ羣,注意實驗報告重點是運行結果,遇到的問題(工具查找,安裝,使用,程序的編輯,調試,運行等)、解決辦法(空洞的方法如「查網絡」、「問同窗」、「看書」等一概得0分)以及分析(從中能夠獲得什麼啓示,有什麼收穫,教訓等);java

3.實驗報告中統計本身的PSP(Personal Software Process)時間:算法

步驟 耗時 百分比
需求分析
設計
代碼實現
測試
分析總結

實驗內容

1、兩人一組結對編程:

  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;

    }*/

最後的運行結果以下圖所示:
網絡

2、結對編程:1人負責客戶端,一人負責服務器

  1. 注意責任歸宿,要會經過測試證實本身沒有問題
  2. 基於Java Socket實現客戶端/服務器功能,傳輸方式用TCP
  3. 客戶端讓用戶輸入中綴表達式,而後把中綴表達式調用MyBC.java的功能轉化爲後綴表達式,把後綴表達式經過網絡發送給服務器
  4. 服務器接收到後綴表達式,調用MyDC.java的功能計算後綴表達式的值,把結果發送給客戶端
  5. 客戶端顯示服務器發送過來的結果
  6. 上傳測試結果截圖和碼雲連接

服務器的代碼以下:app

/**
 * 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){}
        }
    }
}

客戶端的代碼以下socket

/**
 * 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) {
            }
        }
    }
}

3、加密結對編程: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();
        //一、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();
                //二、調用accept()方法開始監聽,等待客戶端的鏈接
                //使用accept()阻塞等待客戶請求,有客戶
                //請求到來則產生一個Socket對象,並繼續執行
            }catch(Exception e) {
                System.out.println("Error."+e);
                //出錯,打印出錯信息
            }
            //三、獲取輸入流,並讀取客戶端信息
            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();
            //從標準輸入讀入一字符串
            //四、獲取輸出流,響應客戶端的請求
            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();
                //從系統標準輸入讀入一字符串
            } //繼續循環

            //五、關閉資源
            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 {
            // 一、建立客戶端Socket,指定服務器地址和端口
            // Socket socket=new Socket("127.0.0.1",5200);
            Socket socket = new Socket("127.0.0.1", 9999);
            System.out.println("客戶端啓動成功");
            // 二、獲取輸出流,向服務器端發送信息
            // 向本機的52000端口發出客戶請求
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            // 由系統標準輸入設備構造BufferedReader對象
            PrintWriter write = new PrintWriter(socket.getOutputStream());
            // 由Socket對象獲得輸出流,並構造PrintWriter對象
            //三、獲取輸入流,並讀取服務器端的響應信息
            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(); // 從系統標準輸入讀入一字符串
            } // 繼續循環
            //四、關閉資源
            write.close(); // 關閉Socket輸出流
            in.close(); // 關閉Socket輸入流
            socket.close(); // 關閉Socket
        } catch (Exception e) {
            System.out.println("can not listen to:" + e);// 出錯,打印出錯信息
        }
    }

}

4、密鑰分發結對編程:1人負責客戶端,一人負責服務器

  1. 注意責任歸宿,要會經過測試證實本身沒有問題
  2. 基於Java Socket實現客戶端/服務器功能,傳輸方式用TCP
  3. 客戶端讓用戶輸入中綴表達式,而後把中綴表達式調用MyBC.java的功能轉化爲後綴表達式,把後綴表達式用3DES或AES算法加密經過網絡把密文發送給服務器
  4. 客戶端和服務器用DH算法進行3DES或AES算法的密鑰交換
  5. 服務器接收到後綴表達式表達式後,進行解密,而後調用MyDC.java的功能計算後綴表達式的值,把結果發送給客戶端
  6. 客戶端顯示服務器發送過來的結果
  7. 上傳測試結果截圖和碼雲連接

5、完整性校驗結對編程: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%
相關文章
相關標籤/搜索