20175325 《JAVA程序設計》實驗五《網絡編程與安全》實驗報告

20175325 《JAVA程序設計》實驗五《網絡編程與安全》實驗報告

1、實驗報告封面
課程:Java程序設計 班級:1753班 姓名:石淦銘
學號:20175325
指導教師:婁嘉鵬 實驗日期:2019年5月28日
實驗序號:實驗五
實驗名稱:網絡編程與安全html

2、實驗內容及步驟:java

(一)、實驗一
一、題目:git

  • 兩人一組結對編程:
  • 參考http://www.cnblogs.com/rocedu/p/6766748.html#SECDSA
  • 結對實現中綴表達式轉後綴表達式的功能 MyBC.java
  • 結對實現從上面功能中獲取的表達式中實現後綴表達式求值的功能,調用MyDC.java
  • 上傳測試代碼運行結果截圖和碼雲連接

二、解答:算法

  • 由中綴式求得後綴式可使用棧,僞代碼以下:
    • 設立一個棧,存放運算符,首先棧爲空;
    • 從左到右掃描中綴式,若遇到操做數,直接輸出,並輸出一個空格做爲兩個操做數的分隔符;
    • 若遇到運算符,則與棧頂比較,比棧頂級別高則進棧,不然退出棧頂元素並輸出,而後輸出一個空格做分隔符;
    • 若遇到左括號,進棧;若遇到右括號,則一直退棧輸出,直到退到左括號止。
    • 當棧變成空時,輸出的結果即爲後綴表達式。
  • 後綴表達式求值的僞代碼以下:
    • 設置一個操做數棧,開始棧爲空;
    • 從左到右掃描後綴表達式,遇操做數,進棧;
    • 若遇運算符,則從棧中退出兩個元素,先退出的放到運算符的右邊,後退出的放到運算符左邊,運算後的結果再進棧,直到後綴表達式掃描完畢。
    • 重複以上步驟,直至後綴表達式結束,棧中最後一個數字就是所求表達式的值。
  • 實驗代碼:
    MyBC:
public class MyBC {
    private Stack theStack;
    private String input;
    private String output = "";

    public MyBC(String in) {
        input = in;
        int stackSize = input.length();
        theStack = new Stack(stackSize);
    }

    public String doTrans() {
        for (int j = 0; j < input.length(); j++) {
            char ch = input.charAt(j);
            switch (ch) {
                case '+':
                case '-':
                    gotOper(ch, 1);
                    break;
                case '*':
                case '/':
                    gotOper(ch, 2);
                    break;
                case '(':
                    theStack.push(ch);
                    break;
                case ')':
                    gotParen(ch);
                    break;
                default:
                    output = output + ch;
                    break;
            }
        }
        while (!theStack.isEmpty()) {
            output = output + theStack.pop();
        }
        return output;
    }

    public void gotOper(char opThis, int prec1) {
        while (!theStack.isEmpty()) {
            char opTop = theStack.pop();
            if (opTop == '(') {
                theStack.push(opTop);
                break;
            } else {
                int prec2;
                if (opTop == '+' || opTop == '-')
                    prec2 = 1;
                else
                    prec2 = 2;
                if (prec2 < prec1) {
                    theStack.push(opTop);
                    break;
                } else
                    output = output + opTop;
            }
        }
        theStack.push(opThis);
    }

    public void gotParen(char ch) {
        while (!theStack.isEmpty()) {
            char chx = theStack.pop();
            if (chx == '(')
                break;
            else
                output = output + chx;
        }
    }

    class Stack {
        private int maxSize;
        private char[] stackArray;
        private int top;

        public Stack(int max) {
            maxSize = max;
            stackArray = new char[maxSize];
            top = -1;
        }

        public void push(char j) {
            stackArray[++top] = j;
        }

        public char pop() {
            return stackArray[top--];
        }

        public char peek() {
            return stackArray[top];
        }

        public boolean isEmpty() {
            return (top == -1);
        }
    }
}

MyDC:express

import java.util.StringTokenizer;
import java.util.Stack;
public class MyDC {
    private final char ADD = '+';
    private final char SUBTRACT = '-';
    private final char MULTIPLY = '*';
    private final char DIVIDE = '/';
    private Stack<Integer> stack;
    public MyDC() {
        stack = new Stack<Integer>();
    }
    public int evaluate(String expr) {
        int op1, op2, result = 0;
        String token;
        StringTokenizer tokenizer = new StringTokenizer(expr);
        while (tokenizer.hasMoreTokens()) {
            token = tokenizer.nextToken();
            //若是是運算符,調用isOperator
            if (isOperator(token)) {
                //從棧中彈出操做數2
                op2 = stack.pop();
                //從棧中彈出操做數1
                op1 = stack.pop();
                //根據運算符和兩個操做數調用evalSingleOp計算result;
                result=evalSingleOp(token.charAt(0), op1, op2);
                //計算result入棧;
                stack.push(result);
            } else//若是是操做數
                //操做數入棧;
                stack.push(Integer.parseInt(token));
        }
        return result;
    }
    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人負責客戶端,一人負責服務器
  • 注意責任歸宿,要會經過測試證實本身沒有問題
  • 基於Java Socket實現客戶端/服務器功能,傳輸方式用TCP
  • 客戶端讓用戶輸入中綴表達式,而後把中綴表達式調用MyBC.java的功能轉化爲後綴表達式,把後綴表達式經過網絡發送給服務器
  • 服務器接收到後綴表達式,調用MyDC.java的功能計算後綴表達式的值,把結果發送給客戶端
  • 客戶端顯示服務器發送過來的結果
  • 上傳測試結果截圖和碼雲連接

二、解答:數組

  • 對象創建方法:使用Socket類
  • Socket構造方法:Socket(String host,int port)
  • ServerSocket對象與服務器端套接字
  • 構造方法:ServerSocket(int port)
  • 使用方法accept()將客戶端的套接字和服務器端的套接字鏈接起來
  • 套接字通訊基本原則:
    • 服務器啓動一個專門的線程,在該線程中和客戶的套接字創建鏈接
    • 套接字的輸入流在讀取信息時可能發生阻塞,客戶端和服務器端都須要在一個單獨的線程中讀取信息
  • ServerSocket和Socket不一樣,服務器套接字的角色是,等待來自客戶端的鏈接請求。一旦服務器套接字得到了一個鏈接請求,它就會建立一個Socket實例,以處理和客戶端的通訊。

客戶端:安全

import java.net.*;
import java.io.*;
public class Client
{
    public static void main(String srgs[]) throws Exception
    {
        try
        {
            Socket socket=new Socket("127.0.0.1",5325);
            System.out.println("客戶端啓動成功");
            // 向本機的10001端口發出客戶請求
            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, infix, expression;
            readline = br.readLine(); 
            MyBC theTrans = new MyBC(readline);
            infix = theTrans.doTrans();
            StringBuilder newInfix = new StringBuilder(infix.replace(" ",""));
            for (int i = 1; i < infix.length()+(i+1)/2 ; i=i+2) {
                newInfix.insert(i," ");
            }
            System.out.println("後綴表達式爲: " + newInfix);
            expression=newInfix.toString();

            while (!readline.equals("end")) {
                // 若從標準輸入讀入的字符串爲 "end"則中止循環
                write.println(expression);
                // 將從系統標準輸入讀入的字符串輸出到Server
                write.flush();
                // 刷新輸出流,使Server立刻收到該字符串
                System.out.println("客戶端發來的消息爲:" + expression);
                // 在系統標準輸出上打印讀入的字符串
                System.out.println("服務器發來的結果爲:" + in.readLine());
                // 從Server讀入一字符串,並打印到標準輸出上
                readline = br.readLine(); // 從系統標準輸入讀入一字符串
            } // 繼續循環
            write.close(); // 關閉Socket輸出流
            in.close(); // 關閉Socket輸入流
            socket.close(); // 關閉Socket
        }
        catch (Exception e)
        {
            System.out.println(e);//輸出異常
        }
        finally
        {

        }

    }
}

服務端:服務器

import java.net.*;
import java.io.*;

public class Server{
    public static void main(String srgs[]) throws Exception
    {
        ServerSocket sc = null;
        Socket socket=null;
        try
        {
            MyDC evaluator = new MyDC();
            sc= new ServerSocket(5325);//建立服務器套接字
            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);
            String aline2=in.readLine();
            System.out.println("客戶端發來的信息爲:"+aline2);

            int ans = evaluator.evaluate(aline2);
            out.println(ans);
            System.out.println("result = "+ans);
        } 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;
    }
}

結果截圖:

網絡

(三)、實驗三
一、題目:

  • 加密結對編程:1人負責客戶端,一人負責服務器
  • 注意責任歸宿,要會經過測試證實本身沒有問題
  • 基於Java Socket實現客戶端/服務器功能,傳輸方式用TCP
  • 客戶端讓用戶輸入中綴表達式,而後把中綴表達式調用MyBC.java的功能轉化爲後綴表達式,把後綴表達式用3DES或AES算法加密後經過網絡把密文發送給服務器
  • 服務器接收到後綴表達式表達式後,進行解密(和客戶端協商密鑰,能夠用數組保存),而後調用MyDC.java的功能計算後綴表達式的值,把結果發送給客戶端
  • 客戶端顯示服務器發送過來的結果
  • 上傳測試結果截圖和碼雲連接

二、解答:

(四)、實驗四
一、題目:

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

二、解答:

  • DH算法:
    • DH密鑰交換算法的安全性基於有限域上的離散對數難題。基於這種安全性,經過DH算法進行密鑰分配,使得消息的收發雙方能夠安全地交換一個密鑰,再經過這個密鑰對數據進行加密和解密處理。
    • 建立DH公鑰和私鑰;
    • 再建立共享密鑰。
  • 使用KeyPairGenerator類建立DH公鑰和私鑰
  • 碼雲連接:
    https://gitee.com/sgm5/text1/commit/d0b6bc4ae80ea6862fc098017fb0133035e52694
  • 實驗截圖:

(五)、實驗五
一、題目:

  • 完整性校驗結對編程:1人負責客戶端,一人負責服務器
  • 注意責任歸宿,要會經過測試證實本身沒有問題
  • 基於Java Socket實現客戶端/服務器功能,傳輸方式用TCP
  • 客戶端讓用戶輸入中綴表達式,而後把中綴表達式調用MyBC.java的功能轉化爲後綴表達式,把後綴表達式用3DES或AES算法加密經過網絡把密文和明文的MD5値發送給服務器
  • 客戶端和服務器用DH算法進行3DES或AES算法的密鑰交換
  • 服務器接收到後綴表達式表達式後,進行解密,解密後計算明文的MD5值,和客戶端傳來的MD5進行比較,一致則調用MyDC.java的功能計算後綴表達式的值,把結果發送給客戶端
  • 客戶端顯示服務器發送過來的結果
  • 上傳測試結果截圖和碼雲連接

二、解答:

3、PSP:

步驟 耗時 百分比
需求分析 30 11%
設計 50 19%
代碼實現 90 34%
測試 45 17%
分析總結 50 19%
相關文章
相關標籤/搜索