1、結對實現中綴表達式轉後綴表達式的功能 ,從上面功能中獲取的表達式中實現後綴表達式求值的功能java
2、 基於Java Socket實現客戶端/服務器功能,傳輸方式用TCP,客戶端讓用戶輸入中綴表達式,而後把中綴表達式調用MyBC.java的功能轉化爲後綴表達式,把後綴表達式經過網絡發送給服務器算法
3、服務器接收到後綴表達式表達式後,進行解密(和客戶端協商密鑰,能夠用數組保存),而後調用MyDC.java的功能計算後綴表達式的值,把結果發送給客戶端編程
4、客戶端和服務器用DH算法進行3DES或AES算法的密鑰交換數組
5、客戶端讓用戶輸入中綴表達式,而後把中綴表達式調用MyBC.java的功能轉化爲後綴表達式,把後綴表達式用3DES或AES算法加密經過網絡把密文發送給服務器安全
ipconfig
指令來查詢IP地址創建符號運算的優先級關係表
服務器
重複上步操做直至表達式結果網絡
基於Java Socket實現客戶端/服務器功能,傳輸方式用TCP,客戶端讓用戶輸入中綴表達式,而後把中綴表達式調用MyBC.java的功能轉化爲後綴表達式,把後綴表達式經過網絡發送給服務器;服務器接收到後綴表達式,調用MyDC.java的功能計算後綴表達式的值,把結果發送給客戶端; 客戶端顯示服務器發送過來的結果
/** *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()); } } } } } }
/** *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()); } } } } } }
/** *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<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); }catch(Exception e){ System.out.println(e); } } }
/** *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
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); //出錯,則打印出錯信息 } } }
問題1:沒法進行測試
socket
問題2:進行測試時,報錯input exception reported
函數
問題2解決方案:搜了一下,發現是格式的問題,字符間應有空格相鏈接
學習
問題3:出現java.net.SocketException: Connection reset
,客戶端輸出文件出錯
問題3解決方案:該異常在客戶端和服務器端均有可能發生,引發該異常的緣由有兩個,第一個就是若是一端的Socket被關閉(或主動關閉或者由於異常退出而引發的關閉),另外一端仍發送數據,發送的第一個數據包引起該異常(Connect reset by peer)。另外一個是一端退出,但退出時並未關閉該鏈接,另外一端若是在從鏈接中讀數據則拋出該異常(Connection reset)。簡單的說就是在鏈接斷開後的讀和寫操做引發的。 在讀取信息時不該該關閉客戶端。
問題4:沒法運行程序,報錯
問題4解決方案:從新啓動,或者換個端口,好比以前是4004
,就能夠換成1234
。
步驟 | 耗時(h) | 百分比 |
---|---|---|
設計 | 2 | 20% |
代碼實現 | 5 | 50% |
測試 | 2 | 20% |
分析總結 | 1 | 10% |
本次實驗過程當中出現了不少問題,反反覆覆折騰了一週,不過在不斷地從書中網上查詢解決問題的過程當中,收穫頗豐。其實不論是學習生活仍是從此工做,有時候須要適當地逼一下本身,可能在某一方面投入90%精力但仍不見但願時,咱們須要作的可能就是再努力10%。這應該是本學期最後一次實驗了,雖然Java實驗真的磨人,不過不論從知識的提高仍是耐力的磨練,總算是有所收穫,仍是挺感謝婁老師。但願本身之後也能屏住最後一口氣,撐住往前走。