20145228 《Java程序設計》實驗報告五:Java網絡編程


實驗內容

1.用書上的TCP代碼,實現服務器與客戶端。

2.客戶端與服務器連接

3.客戶端中輸入明文,利用DES算法加密,DES的秘鑰用RSA公鑰密碼中服務器的公鑰加密,計算明文的Hash函數值,一起傳送給客戶端

4.客戶端用RSA公鑰密碼中服務器的私鑰解密DES的,秘鑰,用秘鑰對密文進行解密,得出明文。計算求得明文的Hash函數值,檢查是否與傳送過來的一致,如果一致,則表示匹配成功。

實驗步驟

結對實驗

•我和20145213祁瑋組隊進行實驗

•我負責服務器的部分,祁瑋負責客戶端部分

IP和端口

•尋找本機的IP地址也就是IPv4的地址可以通過命令行的ipconfig命令來查找。

匹配成功!

•有了IP地址計算機就可以找到對方,但是一個計算機設有多個端口來運行多個網絡程序,每個網絡程序占用不同的端口,所以就算找到了,要想連接起來,還需要知道端口,注意服務器和客戶端的端口必須要統一。

•在硬件上規定,端口的號碼必須位於0-65535之間,每個端口唯一的對應一個網絡程序,一個網絡程序可以使用多個端口。這樣一個網絡程序運行在一台計算上時,不管是客戶端還是服務器,都是至少占用一個端口進行網絡通訊。在接收數據時,首先發送給對應的計算機,然后計算機根據端口把數據轉發給對應的程序。

•有了IP地址和端口的概念以后,在進行網絡通訊交換時,就可以通過IP地址查找到該台計算機,然后通過端口標識這台計算機上的一個唯一的程序。這樣就可以進行網絡數據的交換了。

服務器端網絡操作步驟

•服務器屬於被動等待連接,所以首先要進行監聽端口,等待客戶端進行連接。

•在客戶端連接之后,服務器就獲得一個與客戶端之間的連接,二者就可以通過這個連接進行數據交換了。

•服務器接收到客戶端傳來的數據之后要進行處理,針對本次實驗來說,客戶端傳來的數據是加密過的,所以服務器需要進行解密的操作:

1.首先要使用服務器端RSA的私鑰對DES的密鑰進行解密

2.再將十六進制數據轉換成十進制

3.之后用解密得到的DES密鑰對DES進行解密

4.然后使用解密得到的DES對十進制進制密文數據進行解密

5.最后將得到的十進制明文用“UTF-8”轉碼成明文字符

•解密之后得到明文之后還需要驗證數據完整性,在這里使用Hash函數來檢測。

•檢測成功之后再向客戶端返回數據表示匹配成功或者失敗

服務器代碼


        import java.net.*;
        import java.io.*;
        import java.security.*;
        import java.security.spec.*;
        import javax.crypto.*;
        import javax.crypto.spec.*;
        import javax.crypto.interfaces.*;
        import java.security.interfaces.*;
        import java.math.*;
public class ComputeTCPServer{
    public static void main(String srgs[]) throws Exception
    {
        ServerSocket sc = null;
        Socket socket=null;
        try
        {
            sc= new ServerSocket(10001);//創建服務器套接字
            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);
            //使用服務器端RSA的私鑰對DES的密鑰進行解密
            String aline2=in.readLine();
            BigInteger c=new BigInteger(aline2);
            FileInputStream f=new FileInputStream("Skey_RSA_priv.dat");
            ObjectInputStream b=new ObjectInputStream(f);
            RSAPrivateKey prk=(RSAPrivateKey)b.readObject( );
            BigInteger d=prk.getPrivateExponent();
            BigInteger n=prk.getModulus();
            BigInteger m=c.modPow(d,n);
            byte[] keykb=m.toByteArray();
            //使用DES對密文進行解密
            String aline=in.readLine();//讀取客戶端傳送來的數據
            byte[] ctext=parseHexStr2Byte(aline);
            Key k=new  SecretKeySpec(keykb,"DESede");
            Cipher cp=Cipher.getInstance("DESede");
            cp.init(Cipher.DECRYPT_MODE, k);
            byte []ptext=cp.doFinal(ctext);
            String p=new String(ptext,"UTF8");
            System.out.println("從客戶端接收到信息為:"+p); //通過網絡輸出流返回結果給客戶端
            //使用Hash函數檢測明文完整性
            String aline3=in.readLine();
            String x=p;
            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(result);
            if(aline3.equals(result))
            {
                System.out.println("匹配成功");
            }
            out.println("匹配成功");
            out.close();
            in.close();
            sc.close();
        } 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;
    }
}

結果截圖

實驗中遇到的問題

•這是因為我們調用了RSA算法,但是沒有將對應文件放入,只要將Skey_RSA_pub.dat和Skey_RSA_priv.dat兩個文件放在和src同級目錄下就可以了。

感悟

這次實驗也是需要兩人一起組隊完成,一人負責服務器,一人負責客戶端。讓我們學習到了JAVA網絡編程的基本知識和操作,老師給出了代碼,我們要做的就是將這些復雜的代碼重新組裝、整合,然后用這些代碼完成實驗。這次JAVA的實際應用,收獲了許多。

PSP時間

步驟 耗時 百分比
需求設計 30min 30%
設計 30min 30%
代碼實現 15min 15%
測試 15min 15%
分析總結 10min 10%

參考資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM