20172303 2017-2018-2 《程序設計與數據結構》實驗五報告

20172303 2017-2018-2 《程序設計與數據結構》實驗五報告

  • 課程:《程序設計與數據結構》
  • 班級: 1723
  • 姓名: 範雯琪
  • 學號:20172303
  • 實驗教師:王志強
  • 助教:張旭升/劉偉康
  • 實驗日期:2018年6月13日
  • 必修/選修: 必修

實驗內容

  • 任務一:實現中綴轉後綴並計算結果的功能
    • 參考數據結構應用
    • 結對實現中綴表達式轉後綴表達式的功能 MyBC.java
    • 結對實現從上面功能中獲取的表達式中實現後綴表達式求值的功能,調用MyDC.java
  • 任務二:基於Java Socket實現客戶端/服務器功能
    • 一人負責客戶端,一人負責服務器
    • 客戶端讓用戶輸入中綴表達式,而後把中綴表達式調用MyBC.java的功能轉化爲後綴表達式,把後綴表達式經過網絡發送給服務器
    • 服務器接收到後綴表達式,調用MyDC.java的功能計算後綴表達式的值,把結果發送給客戶端
    • 客戶端顯示服務器發送過來的結果
  • 任務三:基於任務二,使用3DES或AES算法將後綴表達式進行加密
    • 一人負責客戶端,一人負責服務器
    • 客戶端讓用戶輸入中綴表達式,而後把中綴表達式調用MyBC.java的功能轉化爲後綴表達式,把後綴表達式用3DES或AES算法加密後經過網絡把密文發送給服務器
    • 服務器接收到後綴表達式表達式後,進行解密(和客戶端協商密鑰,能夠用數組保存),而後調用MyDC.java的功能計算後綴表達式的值,把結果發送給客戶端
    • 客戶端顯示服務器發送過來的結果
  • 任務四:基於任務三,使用DH進行密鑰交換
    • 一人負責客戶端,一人負責服務器
    • 客戶端讓用戶輸入中綴表達式,而後把中綴表達式調用MyBC.java的功能轉化爲後綴表達式,把後綴表達式用3DES或AES算法加密經過網絡把密文發送給服務器
    • 客戶端和服務器用DH算法進行3DES或AES算法的密鑰交換
    • 服務器接收到後綴表達式表達式後,進行解密,而後調用MyDC.java的功能計算後綴表達式的值,把結果發送給客戶端
    • 客戶端顯示服務器發送過來的結果
  • 任務五:基於任務四,使用MD5將明文加密
    • 一人負責客戶端,一人負責服務器
    • 客戶端讓用戶輸入中綴表達式,而後把中綴表達式調用MyBC.java的功能轉化爲後綴表達式,把後綴表達式用3DES或AES算法加密經過網絡把密文和明文的MD5値發送給服務器
    • 客戶端和服務器用DH算法進行3DES或AES算法的密鑰交換
    • 服務器接收到後綴表達式表達式後,進行解密,解密後計算明文的MD5值,和客戶端傳來的MD5進行比較,一致則調用MyDC.java的功能計算後綴表達式的值,把結果發送給客戶端
    • 客戶端顯示服務器發送過來的結果

實驗過程及結果

任務一

過程

由於在以前的結對編程中已經實現了這兩個功能,而且老師說能夠直接使用,我就直接使用了以前的InfixToSuffix類和Calculator類進行中綴轉後綴和計算,在ArithmeticTest類中添加代碼後實現。html

運行結果

任務二

原理

TCP協議java

  • TCP是Tranfer Control Protocol的簡稱,是一種面向鏈接的保證可靠傳輸的協議.經過TCP協議傳輸,獲得的是一個順序的無差錯的數據流。
  • 發送方和接收方的成對的兩個socket之間必須創建鏈接,以便在TCP協議的基礎上進行通訊,當一個socket(一般都是server socket)等待創建鏈接時,另外一個socket能夠要求進行鏈接,一旦這兩個socket鏈接起來,它們就能夠進行雙向數據傳輸,雙方均可以進行發送或接收操做。
  • TCP在網絡通訊上有極強的生命力,例如遠程鏈接(Telnet)和文件傳輸(FTP)都須要不定長度的數據被可靠地傳輸。可是可靠的傳輸是要付出代價的,對數據內容正確性的檢驗必然佔用計算機的處理時間和網絡的帶寬

Java.net.Socketgit

  • 此類實現客戶端套接字(也能夠就叫「套接字」)。套接字是兩臺機器間通訊的端點。
    套接字的實際工做由 SocketImpl類的實例執行。應用程序經過更改建立套接字實現的套接字工廠能夠配置它自身,以建立適合本地防火牆的套接字。
  • java在包java.net中提供了兩個類SocketServerSocket,分別用來表示雙向鏈接的客戶端和服務端。這是兩個封裝得很是好的類,使用很方便。
  • 構造方法

    其中address、host和port分別是雙向鏈接中另外一方的IP地址、主機名和端口號,stream指明socket是流socket仍是數據報socket,localPort表示本地主機的端口號,localAddr和bindAddr是本地機器的地址(ServerSocket的主機地址),impl是socket的父類,既能夠用來建立serverSocket又可 以用來建立Socket。count則表示服務端所能支持的最大鏈接數。例如:
  Socket client = new Socket("127.0.01.", 80);
  ServerSocket server = new ServerSocket(80);
  • 注意,在選擇端口時,必須當心。每個端口提供一種特定的服務,只有給出正確的端口,才能得到相應的服務。0~1023的端口號爲系統所保留,例如http服務的端口號爲80,telnet服務的端口號爲21,ftp服務的端口號爲23, 因此咱們在選擇端口號時,最好選擇一個大於1023的數以防止發生衝突。

過程

  • 使用ipconfig在cmd中查看本身的IP地址,要注意的是,在建立Socket的時候,若是是和結對夥伴的話,host要填結對夥伴的IP,而若是是本身既作客戶端又作服務器時,host能夠填127.0.0.1或localhost。
  • 客戶端
    • 建立Socket
    //1.創建客戶端Socket鏈接,指定服務器位置和端口
        Socket socket = new Socket("172.16.43.217",8800);
    • 打開鏈接到Socket的輸入流
    //2.獲得socket讀寫流
    OutputStream outputStream = socket.getOutputStream();
    PrintWriter(outputStream);
    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
    //輸入流
    InputStream inputStream = socket.getInputStream();
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
    • 按照必定的協議對Socket進行讀/寫操做
    Scanner scanner = new Scanner(System.in);
    System.out.println("請輸入計算式:(以空格隔開每一個運算符和運算數)");
    String expr = scanner.nextLine();
    InfixToSuffix infixToSuffix = new InfixToSuffix();
    infixToSuffix.conversion(expr);
    System.out.println("我傳送給服務器的信息爲:"+infixToSuffix.getMessage());
    String info = new String(infixToSuffix.getMessage().getBytes("utf-8"));
    outputStreamWriter.write(info);
    outputStreamWriter.flush();
    socket.shutdownOutput();
    //接收服務器的響應
    String reply = null;
    while (!((reply = bufferedReader.readLine()) == null)){
        System.out.println("接收服務器的信息爲:" + reply);
    }
    • 關閉Socket
    bufferedReader.close();
    inputStream.close();
    outputStreamWriter.close();
    outputStream.close();
    socket.close();
  • 服務器
  • 服務器部分是個人結對夥伴完成的,這裏放他的碼雲連接,其大體過程仍然是:
    • 建立Socket
    • 打開鏈接到Socket的輸入/出流
    • 按照必定的協議對Socket進行讀/寫操做
    • 關閉Socket

運行結果


任務三

原理

DES加密算法算法

  • DES加密是一種對稱加密算法,它是分組密鑰的表明算法,算法和密鑰都須要良好的加密。
  • 實現DES對稱密鑰的步驟有三步:
    • 生成對稱密鑰;
    • 使用對稱密鑰進行加密和解密;
    • 從文件中獲取加密時使用的密鑰,使用密鑰進行解密。
  • 關鍵代碼
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<ptext.length;i++){
    System.out.print(ptext[i]+",");
}
System.out.println("");
byte ctext[]=cp.doFinal(ptext);
for(int i=0;i<ctext.length;i++){
     System.out.print(ctext[i] +",");
}
FileOutputStream f2=new FileOutputStream("SEnc.dat");
f2.write(ctext);

過程

  • 剛開始咱們在任務二的基礎上進行代碼增長,可是在運行時服務器端顯示的是亂碼,後來發現是由於傳輸的格式有問題,婁老師的博客裏給的解密方式解密的必須是byte數組,以後咱們就想辦法把傳過來的信息的格式改爲byte數組,可是嘗試了不少次都失敗了。
  • 而在在上網查的時候發現一篇博客中java的OutputStream.writeUTF()函數介紹了另外一種方法:DataOutputStream/DataInputStream,其中有一個方法叫wrtieUTF,它將 UTF-8 字符串寫入字節流。先寫入以字節表示的 UTF-8 字符串長度(做爲 16 位整數),而後寫入表示字符串字符的字節。使用這個方法,在傳輸以後轉化成byte數組就很方便了。
  • 客戶端
  • 服務器

運行結果


任務四

原理

DH算法編程

  • 在DH算法中,主要數據經過對稱密鑰加密,而使用非對稱加密來分發對稱密鑰,這樣就將二者的優點結合了起來。
  • DH算法是創建在DH公鑰和私鑰的基礎上的,A須要和B共享密鑰時,A和B各自生成DH公鑰和私鑰,公鑰對外公佈而私鑰各自祕密保存。

過程

  • 1.修改原先的key_DH類和keyAgree類中的main方法,使其可以被引用。

  • 2.建立DH公鑰和私鑰,將生成的公鑰文件傳給對方
    客戶端

    服務器

運行結果


任務五

原理

  • 使用Java計算指定字符串的消息摘要。java.security包中的MessageDigest類提供了計算消息摘要的方法。
  • 運行代碼
String x=args[0];
    MessageDigest m=MessageDigest.getInstance("MD5");
    m.update(x.getBytes("UTF8"));
    byte s[ ]=m.digest( );
    String result="";
    for (int i=0; i<s.length; i++){
        result+=Integer.toHexString((0x000000ff & s[i]) | 
0xffffff00).substring(6);
    }
    System.out.println(result);

過程

在任務四的代碼基礎上將運行代碼加入便可。數組

運行結果


實驗過程當中遇到的問題和解決過程

  • 問題1:在第一次運行Socket時拋出IOException錯誤。
  • 問題1解決方法:經過在網上查找發現這個錯誤好像是避免不了的,必須進行捕獲或者拋出。服務器

    在建立socket時若是發生錯誤,將產生IOException,在程序中必須對之做出處理。因此在建立Socket或ServerSocket是必須捕獲或拋出例外。網絡

  • 問題2:在傳輸的過程當中產生錯誤javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
  • 問題2解決方法:經過翻譯,產生的緣由應該是由於服務器和客戶端產生的密鑰不一樣,在把個人密鑰文件複製給他以後就解決了問題。
  • 問題3:在任務三傳輸的過程當中,傳輸過去的一直顯示的是亂碼
  • 問題3解決方法:在剛剛的任務三的實驗過程當中有寫到,咱們找到了另一種方法來解決這個問題。數據結構

其餘(感悟、思考等)

本學期的最後一次實驗了,感受java socket真的很是有意思,最後悔的是當時實驗三的最後一個節點作的不是很好,因此這回又去複習了半天密碼學的相關內容。
回顧一個學期的內容發現本身真的學到了不少,很開心。socket

下學期繼續加油。

參考資料

相關文章
相關標籤/搜索