20165310 Java实验五《网络编程与安全》
20165310 Java實驗五《網絡編程與安全》
任務一
題目:①編寫MyBC.java實現中綴表達式轉后綴表達式的功能;②編寫MyDC.java實現從上面功能中獲取的表達式中實現后綴表達式求值的功能
中綴轉后綴的算法可描述為:
- 設置一個運算符棧,設置一個后綴表達式字符串;
- 從左到右依次對中綴表達式中的每個字符ch分別進行以下處理,直至表達式結束:
- 若ch是左括號‘(’,將其入棧;
- 若ch是數字,將其后連續若干數字添加到后綴表達式字符串之后,并添加空格作為分隔符;
- 若ch是運算符,先將棧頂若干優先級高于ch的運算符出棧,添加到后綴表達式字符串之后,再將ch入棧。當‘(’運算符在棧中時,它的優先級最低。
- 若ch是‘)’,則若干運算符全部出棧,直到出棧的是左括號,一對括號匹配。
- 若表達式結束,將棧中運算符全部出棧,添加到后綴表達式字符串之后。
后綴表達式求值的算法可描述為(參考:婁老師的博客):
- 設置一個操作數棧,從左向右依次對后綴表達式字符串中的每個字符ch進行處理;
- 若ch是數字,先將其后連續若干數字轉化為整數,再將該整數入棧;
- 若ch是運算符,出棧兩個值進行運算,運算結果再入棧;
- 重復以上步驟,直至后綴表達式結束,棧中最后一個數字就是所求表達式的值。
在我之前的實驗一中有更為詳細的代碼與解釋:《20165310_JavaExp1_Java開發環境的熟悉》
添加的測試代碼:
public class NewMyDCTester {public static void main(String [] args) {String expression;int result;try{Scanner in = new Scanner(System.in);NewMyDC evaluator = new NewMyDC();System.out.println ("Enter a valid postfix expression: ");expression = in.nextLine();String postfix = MyBC.toPostfix(expression);System.out.println ("The postfix expression is :" + postfix);result = evaluator.value (postfix);System.out.println ("That expression equals :" + result);}catch (Exception IOException){System.out.println("Input exception reported");}} }?
實驗運行結果:
任務二
題目:①結對編程:一人負責客戶端,另一人負責服務器;②注意責任歸宿,要會通過測試證明自己沒有問題;③基于Java Socket實現客戶端/服務器功能,傳輸方式用TCP;④客戶端讓用戶輸入中綴表達式,然后把中綴表達式調用MyBC.java的功能轉化為后綴表達式,把后綴表達式通過網絡發送給服務器;⑤服務器接收到后綴表達式,調用MyDC.java的功能計算后綴表達式的值,把結果發送給客戶端;⑥客戶端顯示服務器發送過來的結果
我的任務是客戶端,代碼如下:
import java.io.DataInputStream; import java.io.DataOutputStream; import java.net.Socket; import java.util.Scanner;public class Client {public static void main(String[] args) {String str;System.out.println("請輸入要計算的中綴式:");Scanner scanner=new Scanner(System.in);str=scanner.nextLine();Socket myClientSocket;DataInputStream in=null;DataOutputStream out=null;ChangeExpress chedExp=new ChangeExpress();chedExp.setOriginalExpression(str);chedExp.changedWay();System.out.println("發送給服務器的后綴式為:"+chedExp.changedExpression);try {myClientSocket = new Socket("10.1.1.165",2010);System.out.println("客戶端已啟動");in=new DataInputStream(myClientSocket.getInputStream());out=new DataOutputStream(myClientSocket.getOutputStream());out.writeUTF(chedExp.changedExpression);String answer=in.readUTF();System.out.println("服務器端計算結果是:"+answer);Thread.sleep(500);}catch (Exception e){System.out.println("服務器已斷開"+e);}} }java.net.Socket
- 套接字是一個網絡連接的端點。在java中,使用java.net.Socket對象來表示一個套接字。要創建一個套接字,可以使用Socket的構造方法,如:public Socket(java.lang.String host, int port)。其中,host是遠程機器名或IP地址,port是遠程應用程序的端口號。上述代碼中,IP地址為:"10.1.1.165",端口號為:2010。
- 成功創建Socket類的一個實例后,就可以使用它發送或接收字節流。發送字節流,必須先調用Socket類的getOutputStream方法來獲取一個java.io.OutputStream對象。接收字節流,可以調用Socket類的getInputStream方法,它返回一個java.io.InputStream。
運行結果
任務三
題目:①客戶端讓用戶輸入中綴表達式,然后把中綴表達式調用MyBC.java的功能轉化為后綴表達式,把后綴表達式用3DES或AES算法加密后通過網絡把密文發送給服務器;②服務器接收到后綴表達式表達式后,進行解密(和客戶端協商密鑰,可以用數組保存),然后調用MyDC.java的功能計算后綴表達式的值,把結果發送給客戶端。其他要求同任務二。
客戶端RSA加密代碼
import java.net.*; import java.io.*; import java.security.*; import javax.crypto.*; import javax.crypto.spec.*; import java.security.spec.*; import javax.crypto.interfaces.*; import java.security.interfaces.*; import java.math.*;public class Client {public static void main(String srgs[]) throws Exception {try {KeyGenerator kg = KeyGenerator.getInstance("DESede");kg.init(168);SecretKey k = kg.generateKey();byte[] ptext = k.getEncoded();Socket socket = new Socket("192.168.43.109", 2010);BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));//RSA算法,使用服務器端的公鑰對DES的密鑰進行加密FileInputStream f3 = new FileInputStream("Skey_RSA_pub.dat");ObjectInputStream b2 = new ObjectInputStream(f3);RSAPublicKey pbk = (RSAPublicKey) b2.readObject();BigInteger e = pbk.getPublicExponent();BigInteger n = pbk.getModulus();BigInteger m = new BigInteger(ptext);BigInteger c = m.modPow(e, n);String cs = c.toString();out.println(cs); // 通過網絡將加密后的秘鑰傳送到服務器System.out.println("請輸入中綴式:");//用DES加密明文得到密文String s = stdin.readLine(); // 從鍵盤讀入待發送的數據String plain = MyBC.changeWay(s);Cipher cp = Cipher.getInstance("DESede");cp.init(Cipher.ENCRYPT_MODE, k);byte ptext1[] = plain.getBytes("UTF8");byte ctext[] = cp.doFinal(ptext1);String str = parseByte2HexStr(ctext);out.println(str); // 通過網絡將密文傳送到服務器System.out.println("從服務器接收到的結果為:" + str); // 輸出結果} catch (Exception e) {System.out.println("服務器斷開連接"+e);//輸出異常}}}?
實驗結果
任務四
- 題目:任務三基礎上增加客戶端和服務器用DH算法進行3DES或AES算法的密鑰交換。
- 創建DH公鑰和私鑰:
- 創建共享密鑰
DH算法中,A可以用自己的密鑰和B的公鑰按照一定方法生成一個密鑰,B也可以用自己的密鑰和A的公鑰按照一定方法生成一個密鑰,由于一些數學規律,這兩個密鑰完全相同。這樣,A和B間就有了一個共同的密鑰可以用于各種加密。本實例介紹Java中在上一小節的基礎上如何利用DH公鑰和私鑰各自創建共享密鑰。
import java.io.*; import java.math.*; import java.security.*; import java.security.spec.*; import javax.crypto.*; import javax.crypto.spec.*; import javax.crypto.interfaces.*;public class KeyAgree{public static void main(String args[ ]) throws Exception{// 讀取對方的DH公鑰FileInputStream f1=new FileInputStream(args[0]);ObjectInputStream b1=new ObjectInputStream(f1);PublicKey pbk=(PublicKey)b1.readObject( ); //讀取自己的DH私鑰FileInputStream f2=new FileInputStream(args[1]);ObjectInputStream b2=new ObjectInputStream(f2);PrivateKey prk=(PrivateKey)b2.readObject( );// 執行密鑰協定KeyAgreement ka=KeyAgreement.getInstance("DH");ka.init(prk);ka.doPhase(pbk,true);//生成共享信息byte[ ] sb=ka.generateSecret();for(int i=0;i<sb.length;i++){System.out.print(sb[i]+",");}SecretKeySpec k=new SecretKeySpec(sb,"DESede");} }運行結果
任務五
題目:任務四的基礎上,在服務器接收到后綴表達式表達式后,進行解密,解密后計算明文的MD5值,和客戶端傳來的MD5進行比較,一致則調用MyDC.java的功能計算后綴表達式的值,把結果發送給客戶端。
MD5算法
使用Java計算指定字符串的消息摘要。
java.security包中的MessageDigest類提供了計算消息摘要的方法,最后的實現代碼:
運行結果
問題總結
- 在端口和IP正確的情況下客戶端與服務器無法連接:
- 是由于沒有處于同一網絡中,必須在同一網絡中可以連接。
- 服務器接受不到客戶端發送的消息
- 由于阻塞問題,可用Thread類解決,或者可以改變輸入輸出流,在任務二中,我直接修改引用了書上例子三的代碼就可以完成,但是在任務三中由于阻塞的原因無法進行通信,參考狄維佳學姐的博客,將DataOutputStream更改為PrintWriter,將DataInputStream更改為BufferReader,解決了阻塞問題。
轉載于:https://www.cnblogs.com/atbaoi/p/9101025.html
總結
以上是生活随笔為你收集整理的20165310 Java实验五《网络编程与安全》的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Visual Studio 2017 A
- 下一篇: Java:清空文件内容