20165310 Java实验五《网络编程与安全》
20165310 Java實(shí)驗(yàn)五《網(wǎng)絡(luò)編程與安全》
任務(wù)一
題目:①編寫MyBC.java實(shí)現(xiàn)中綴表達(dá)式轉(zhuǎn)后綴表達(dá)式的功能;②編寫MyDC.java實(shí)現(xiàn)從上面功能中獲取的表達(dá)式中實(shí)現(xiàn)后綴表達(dá)式求值的功能
中綴轉(zhuǎn)后綴的算法可描述為:
- 設(shè)置一個運(yùn)算符棧,設(shè)置一個后綴表達(dá)式字符串;
- 從左到右依次對中綴表達(dá)式中的每個字符ch分別進(jìn)行以下處理,直至表達(dá)式結(jié)束:
- 若ch是左括號‘(’,將其入棧;
- 若ch是數(shù)字,將其后連續(xù)若干數(shù)字添加到后綴表達(dá)式字符串之后,并添加空格作為分隔符;
- 若ch是運(yùn)算符,先將棧頂若干優(yōu)先級高于ch的運(yùn)算符出棧,添加到后綴表達(dá)式字符串之后,再將ch入棧。當(dāng)‘(’運(yùn)算符在棧中時,它的優(yōu)先級最低。
- 若ch是‘)’,則若干運(yùn)算符全部出棧,直到出棧的是左括號,一對括號匹配。
- 若表達(dá)式結(jié)束,將棧中運(yùn)算符全部出棧,添加到后綴表達(dá)式字符串之后。
后綴表達(dá)式求值的算法可描述為(參考:婁老師的博客):
- 設(shè)置一個操作數(shù)棧,從左向右依次對后綴表達(dá)式字符串中的每個字符ch進(jìn)行處理;
- 若ch是數(shù)字,先將其后連續(xù)若干數(shù)字轉(zhuǎn)化為整數(shù),再將該整數(shù)入棧;
- 若ch是運(yùn)算符,出棧兩個值進(jìn)行運(yùn)算,運(yùn)算結(jié)果再入棧;
- 重復(fù)以上步驟,直至后綴表達(dá)式結(jié)束,棧中最后一個數(shù)字就是所求表達(dá)式的值。
在我之前的實(shí)驗(yàn)一中有更為詳細(xì)的代碼與解釋:《20165310_JavaExp1_Java開發(fā)環(huán)境的熟悉》
添加的測試代碼:
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");}} }?
實(shí)驗(yàn)運(yùn)行結(jié)果:
任務(wù)二
題目:①結(jié)對編程:一人負(fù)責(zé)客戶端,另一人負(fù)責(zé)服務(wù)器;②注意責(zé)任歸宿,要會通過測試證明自己沒有問題;③基于Java Socket實(shí)現(xiàn)客戶端/服務(wù)器功能,傳輸方式用TCP;④客戶端讓用戶輸入中綴表達(dá)式,然后把中綴表達(dá)式調(diào)用MyBC.java的功能轉(zhuǎn)化為后綴表達(dá)式,把后綴表達(dá)式通過網(wǎng)絡(luò)發(fā)送給服務(wù)器;⑤服務(wù)器接收到后綴表達(dá)式,調(diào)用MyDC.java的功能計算后綴表達(dá)式的值,把結(jié)果發(fā)送給客戶端;⑥客戶端顯示服務(wù)器發(fā)送過來的結(jié)果
我的任務(wù)是客戶端,代碼如下:
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("發(fā)送給服務(wù)器的后綴式為:"+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("服務(wù)器端計算結(jié)果是:"+answer);Thread.sleep(500);}catch (Exception e){System.out.println("服務(wù)器已斷開"+e);}} }java.net.Socket
- 套接字是一個網(wǎng)絡(luò)連接的端點(diǎn)。在java中,使用java.net.Socket對象來表示一個套接字。要創(chuàng)建一個套接字,可以使用Socket的構(gòu)造方法,如:public Socket(java.lang.String host, int port)。其中,host是遠(yuǎn)程機(jī)器名或IP地址,port是遠(yuǎn)程應(yīng)用程序的端口號。上述代碼中,IP地址為:"10.1.1.165",端口號為:2010。
- 成功創(chuàng)建Socket類的一個實(shí)例后,就可以使用它發(fā)送或接收字節(jié)流。發(fā)送字節(jié)流,必須先調(diào)用Socket類的getOutputStream方法來獲取一個java.io.OutputStream對象。接收字節(jié)流,可以調(diào)用Socket類的getInputStream方法,它返回一個java.io.InputStream。
運(yùn)行結(jié)果
任務(wù)三
題目:①客戶端讓用戶輸入中綴表達(dá)式,然后把中綴表達(dá)式調(diào)用MyBC.java的功能轉(zhuǎn)化為后綴表達(dá)式,把后綴表達(dá)式用3DES或AES算法加密后通過網(wǎng)絡(luò)把密文發(fā)送給服務(wù)器;②服務(wù)器接收到后綴表達(dá)式表達(dá)式后,進(jìn)行解密(和客戶端協(xié)商密鑰,可以用數(shù)組保存),然后調(diào)用MyDC.java的功能計算后綴表達(dá)式的值,把結(jié)果發(fā)送給客戶端。其他要求同任務(wù)二。
客戶端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算法,使用服務(wù)器端的公鑰對DES的密鑰進(jìn)行加密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); // 通過網(wǎng)絡(luò)將加密后的秘鑰傳送到服務(wù)器System.out.println("請輸入中綴式:");//用DES加密明文得到密文String s = stdin.readLine(); // 從鍵盤讀入待發(fā)送的數(shù)據(jù)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); // 通過網(wǎng)絡(luò)將密文傳送到服務(wù)器System.out.println("從服務(wù)器接收到的結(jié)果為:" + str); // 輸出結(jié)果} catch (Exception e) {System.out.println("服務(wù)器斷開連接"+e);//輸出異常}}}?
實(shí)驗(yàn)結(jié)果
任務(wù)四
- 題目:任務(wù)三基礎(chǔ)上增加客戶端和服務(wù)器用DH算法進(jìn)行3DES或AES算法的密鑰交換。
- 創(chuàng)建DH公鑰和私鑰:
- 創(chuàng)建共享密鑰
DH算法中,A可以用自己的密鑰和B的公鑰按照一定方法生成一個密鑰,B也可以用自己的密鑰和A的公鑰按照一定方法生成一個密鑰,由于一些數(shù)學(xué)規(guī)律,這兩個密鑰完全相同。這樣,A和B間就有了一個共同的密鑰可以用于各種加密。本實(shí)例介紹Java中在上一小節(jié)的基礎(chǔ)上如何利用DH公鑰和私鑰各自創(chuàng)建共享密鑰。
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( );// 執(zhí)行密鑰協(xié)定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");} }運(yùn)行結(jié)果
任務(wù)五
題目:任務(wù)四的基礎(chǔ)上,在服務(wù)器接收到后綴表達(dá)式表達(dá)式后,進(jìn)行解密,解密后計算明文的MD5值,和客戶端傳來的MD5進(jìn)行比較,一致則調(diào)用MyDC.java的功能計算后綴表達(dá)式的值,把結(jié)果發(fā)送給客戶端。
MD5算法
使用Java計算指定字符串的消息摘要。
java.security包中的MessageDigest類提供了計算消息摘要的方法,最后的實(shí)現(xiàn)代碼:
運(yùn)行結(jié)果
問題總結(jié)
- 在端口和IP正確的情況下客戶端與服務(wù)器無法連接:
- 是由于沒有處于同一網(wǎng)絡(luò)中,必須在同一網(wǎng)絡(luò)中可以連接。
- 服務(wù)器接受不到客戶端發(fā)送的消息
- 由于阻塞問題,可用Thread類解決,或者可以改變輸入輸出流,在任務(wù)二中,我直接修改引用了書上例子三的代碼就可以完成,但是在任務(wù)三中由于阻塞的原因無法進(jìn)行通信,參考狄維佳學(xué)姐的博客,將DataOutputStream更改為PrintWriter,將DataInputStream更改為BufferReader,解決了阻塞問題。
轉(zhuǎn)載于:https://www.cnblogs.com/atbaoi/p/9101025.html
總結(jié)
以上是生活随笔為你收集整理的20165310 Java实验五《网络编程与安全》的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Visual Studio 2017 A
- 下一篇: Java:清空文件内容