20145236 实验五 Java网络编程

实验内容

1.运行TCP代码,结对进行,一人服务器,一人客户端;

2.利用加解密代码包,编译运行代码,一人加密,一人解密;

3.集成代码,一人加密后通过TCP发送;

注:加密使用AES或者DES/AES或者DES加密密钥key并发送,使用服务器的公钥加密/公钥算法使用RSA或DH/检验发送信息的完整性使用MD5或者SHA3;

4.完成Blog。

PSP实践

步骤 耗时 百分比
需求分析 1h 20%
设计 2h 40%
代码实现 40min 15%
测试 40min 15%
分析总结 30min 10%

实验步骤

1.综述

本次实验的实验内容较少,但是准备工作非常多;在此次实验中,本小组仍然采用“边学习,边实验”的方法,虽然过程较曲折,但最后结果很成功。

2.学习TCP

  • 查找自己主机的IP地址,确定端口号。在命令行中输入ipconfig

  • 用BufferedReader获取从服务器传入的数据流,再用PrintWriter获取从客户端传出的输出流。

  • 用RSA算法加密,加密使用服务器的公钥,再将加密后的密钥传给服务器。

  • 用DES算法加密输入的明文,将加密后的密文传给服务器。

  • 使用Hash函数,计算明文的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 Server {

    public static void main(String srgs[]) throws Exception {

       ServerSocket sc = null;

       Socket socket = null;

       try {

           sc = new ServerSocket(8029);// 创建服务器套接字

           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);

           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();

           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); // 通过网络输出流返回结果给客户端

           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 String parseByte2HexStr(byte buf[]) {

       StringBuffer sb = new StringBuffer();

       for (int i = 0; i < buf.length; i++) {

           String hex = Integer.toHexString(buf[i] & 0xFF);

           if (hex.length() == 1) {

              hex = '0' + hex;

           }

           sb.append(hex.toUpperCase());

       }

       return sb.toString();

    }

    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;

    }

}
  • 运行结果:

客户端:

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[] ptext2 = k.getEncoded();

           // 创建连接特定服务器的指定端口的Socket对象

           Socket socket = new Socket("222.28.128.119", 8028);

           // 网络输入流

           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));

           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(ptext2);

           BigInteger c = m.modPow(e, n);

           String cs = c.toString();

           out.println(cs); // 通过网络传送到服务器

           System.out.print("请输入待发送的数据:");

           String s = stdin.readLine();

           Cipher cp = Cipher.getInstance("DESede");

           cp.init(Cipher.ENCRYPT_MODE, k);

           byte ptext[] = s.getBytes("UTF8");

           byte ctext[] = cp.doFinal(ptext);

           String str = parseByte2HexStr(ctext);

           out.println(str);

           String x = s;

           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);

           out.println(result);

           str = in.readLine();// 从网络输入流读取结果

           System.out.println("从服务器接收到的结果为:" + str); // 输出服务器返回的结果

       } catch (Exception e) {

           System.out.println(e);

       } finally {

       }

    }

    public static String parseByte2HexStr(byte buf[]) {

       StringBuffer sb = new StringBuffer();

       for (int i = 0; i < buf.length; i++) {

           String hex = Integer.toHexString(buf[i] & 0xFF);

           if (hex.length() == 1) {

              hex = '0' + hex;

           }

           sb.append(hex.toUpperCase());

       }

       return sb.toString();

    }

    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;

    }

}
  • 运行结果:

运行加解密包中的程序

import java.io.*;

import javax.crypto.*;

public class Skey_DES{ 

         public static void main(String args[]) throws Exception{

                  KeyGenerator kg=KeyGenerator.getInstance("DESede");

                  kg.init(168);

        SecretKey k=kg.generateKey( );

        FileOutputStream  f=new FileOutputStream("key1.dat");

             ObjectOutputStream b=new  ObjectOutputStream(f);

             b.writeObject(k);

    }

}
import java.io.*;

import java.security.*;

public class Skey_kb{

   public static void main(String args[]) throws Exception{

         FileInputStream f=new FileInputStream("key1.dat");

         ObjectInputStream b=new ObjectInputStream(f);

         Key k=(Key)b.readObject( );

        byte[ ] kb=k.getEncoded( );

        FileOutputStream  f2=new FileOutputStream("keykb1.dat");

            f2.write(kb);

        // 打印密钥编码中的内容

        for(int i=0;i<kb.length;i++){

             System.out.print(kb[i]+",");

        }

   }

}

Java网络编程的一般步骤

(1)客户端(Client)

客户端是指网络编程中首先发起连接的程序,客户端一般实现程序界面和基本逻辑实现,在进行实际的客户端编程时,客户端的编程主要由三个步骤实现:

① 建立网络连接:连接时需要指定连接到的服务器的IP地址和端口号,建立完成以后,会形成一条虚拟的连接,后续的操作就可以通过该连接实现数据交换了。

②交换数据:连接建立以后,就可以通过这个连接交换数据了。交换数据严格按照请求响应模型进行,由客户端发送一个请求数据到服务器,服务器反馈一个响应数据给客户端,如果客户端不发送请求则服务器端就不响应。根据逻辑需要,可以多次交换数据,但是还是必须遵循请求响应模型。

③关闭网络连接:在数据交换完成以后,关闭网络连接,释放程序占用的端口、内存等系统资源,结束网络编程。

(2)服务器端(Server)

服务器端(Server)是指在网络编程中被动等待连接的程序,服务器端一般实现程序的核心逻辑以及数据存储等核心功能。服务器端的编程步骤和客户端不同,是由四个步骤实现,依次是:

①监听端口: 服务器端属于被动等待连接,所以服务器端启动以后,不需要发起连接,而只需要监听本地计算机的某个固定端口即可。这个端口就是服务器端开放给客户端的端口,服务器端程序运行的本地计算机的IP地址就是服务器端程序的IP地址。

②获得连接:当客户端连接到服务器端时,服务器端就可以获得一个连接,这个连接包含客户端的信息,例如客户端IP地址等等,服务器端和客户端也通过该连接进行数据交换。一般在服务器端编程中,当获得连接时,需要开启专门的线程处理该连接,每个连接都由独立的线程实现。

③交换数据:服务器端通过获得的连接进行数据交换。服务器端的数据交换步骤是首先接收客户端发送过来的数据,然后进行逻辑处理,再把处理以后的结果数据发送给客户端。简单来说,就是先接收再发送,这个和客户端的数据交换数序不同。其实,服务器端获得的连接和客户端连接是一样的,只是数据交换的步骤不同。当然,服务器端的数据交换也是可以多次进行的。

④关闭连接:当服务器程序关闭时,需要关闭服务器端,通过关闭服务器端使得服务器监听的端口以及占用的内存可以释放出来,实现了连接的关闭。

经过以上学习,我们初步掌握了服务器代码与客户端代码特点、运行方式,为进一步开展代码整合打下基础。

在编译客户端时,eclipse显示此处有错误:InetAddress addr = InetAddress.getByName(10.43.41.202);经检查,是没有合法输入,将IP地址用引号表示,程序可以正常运行。

实验中遇到的问题

问题一:Java.net.BindException:Address already in use: JVM_Bind该异常发生在服务器端进行new ServerSocket(port)(port是一个0,65536的整型值)操作时。异常的原因是以为与port一样的一个端口已经被启动,并进行监听。此时用netstat –an命令,可以看到一个Listending状态的端口。只需要找一个没有被占用的端口就能解决这个问题。

问题二:java.net.ConnectException: Connection refused: connect该异常发生在客户端进行new Socket(ip, port)操作时,该异常发生的原因是或者具有ip地址的机器不能找到(也就是说从当前机器不存在到指定ip路由),或者是该ip存在,但找不到指定的端口进行监听。出现该问题,首先检查客户端的ip和port是否写错了,如果正确则从客户端ping一下服务器看是否能ping通,如果能ping通(服务服务器端把ping禁掉则需要另外的办法),则看在服务器端的监听指定端口的程序是否启动,这个肯定能解决这个问题。

问题三:java.net.SocketException: (Connection reset或者Connect reset by peer:Socket write error)该异常在客户端和服务器端均有可能发生,引起该异常的原因有两个,第一个就是如果一端的Socket被关闭(或主动关闭或者因为异常退出而引起的关闭),另一端仍发送数据,发送的第一个数据包引发该异常(Connect reset by peer)。另一个是一端退出,但退出时并未关闭该连接,另一端如果在从连接中读数据则抛出该异常(Connection reset)。简单的说就是在连接断开后的读和写操作引起的。

20145236 《Java程序设计》实验五实验报告的更多相关文章

  1. 20145222黄亚奇《Java程序设计》实验五实验报告

    20145222 <Java程序设计>实验五实验报告 实验内容 1.掌握Socket程序的编写: 2.掌握密码技术的使用: 3.设计安全传输系统. 实验步骤 本次实验我的结对编程对象是20 ...

  2. 20145315 《Java程序设计》实验五实验报告

    20145315 <Java程序设计>实验五实验报告 实验五 Java网络编程 我负责服务器部分,王嘉澜负责客户端部分:http://www.cnblogs.com/SJZGM10/p/5 ...

  3. 20145227 《Java程序设计》实验五实验报告

    20145227 <Java程序设计>实验五实验报告 实验内容 1.掌握Socket程序的编写: 2.掌握密码技术的使用: 3.设计安全传输系统. 实验过程 1.先运行TCP代码,一人服务 ...

  4. 20145120 《Java程序设计》实验五实验报告

    20145120 <Java程序设计>实验五实验报告 实验名称:Java网络编程 实验内容: 1.掌握Socket程序的编写: 2.掌握密码技术的使用: 3.设计安全传输系统. 实验内容. ...

  5. 20145314郑凯杰 《Java程序设计》实验五 实验报告

    20145314郑凯杰 <Java程序设计>实验五 实验报告 实验搭档王亦徐:http://www.cnblogs.com/1152wyx/p/5471524.html 实验要求 完成实验 ...

  6. 20145328 《Java程序设计》实验五实验报告

    20145328 <Java程序设计>实验五实验报告 实验名称 Java网络编程 实验内容 用书上的TCP代码,实现服务器与客户端. 客户端与服务器连接 客户端中输入明文,利用DES算法加 ...

  7. 20145330《Java程序设计》第一次实验报告

    20145330<Java程序设计>第一次实验报告 实验一Java开发环境的熟悉 实验内容 1.使用JDK编译.运行简单的Java程序: 2.使用Eclipse 编辑.编译.运行.调试Ja ...

  8. 20145320《Java程序设计》第一次实验报告

    20145320<Java程序设计>第一次实验报告 北京电子科技学院(BESTI)实验报告 课程:Java程序设计 班级:1453 指导教师:娄嘉鹏 实验日期:2016.04.08 18: ...

  9. 20145317彭垚 《Java程序设计》第一次实验实验报告

    20145317彭垚 <Java程序设计>第一次实验实验报告 北京电子科技学院(BESTI)实验报告 课程:Java程序设计 班级:1453 指导教师:娄嘉鹏 实验名称:Java开发环境的 ...

  10. #《JAVA程序设计》 20155214 实验五 网络编程与安全

    <JAVA程序设计> 20155214 实验五 网络编程与安全 实验内容 掌握Socket程序的编写: 掌握密码技术的使用: 设计安全传输系统. 实验要求 要求一 结对实现中缀表达式转后缀 ...

随机推荐

  1. [HDOJ3911]Black And White(线段树,区间合并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3911 题意:一个01串,两种操作: 0 a b:查询[a,b]内连续1的最长长度. 1 a b:翻转[ ...

  2. 【Protle99SE】PCB中各层的含义【小汇】

    忽然发现,对solder和paste,layer和plane这两对有些糊涂了,摘录网络中的文章如下: [http://www.360doc.com/content/10/0608/15/514342_ ...

  3. Hibernate+Struts2+jsp 修改用户信息

    在用户列表页面点击修改,进入修改页面 修改薪酬为555,点击提交,重新跳回该页面 修改成功 关键代码如下 基层的代码,这里增加了一个根据用户id查询的方法 dao层 //修改 public USer ...

  4. 3.27考试总结(hnoi难度)

    1 duel1.1 DescriptionK·⁄¶("“uƒ¢y%¥§H5|+ (?1’m" ’m·ø?1§z<k§⁄k<⁄§lm?0,1,2...§zg ‹‰ª«mS ...

  5. shape into blocks--source code in python based on pySpark

    这是微博深度和广度预测的原始代码,写了大约半个月,第一个版本不是这样的,但是这个版本包含所有需要的功能. 模块化的程度也更高.找工作前一直想用python完美解决这个问题,后来发现自己的方法和硬件都有 ...

  6. scala打印九九乘法表的5种实现

    使用scala打印九九乘法表,可以有多种实现方法,实现的过程充分的体现的scala语言的优势和巨大的简洁性和高效性, 下面我用了5种方法实现九九乘法表. 使用类似于java,c++等指令风格的的编程实 ...

  7. js 定时器的使用。 setInterval()

    我需要实现的功能是:点击发送按钮,会出现 “已发送60s后可点击重发”,并且,60s 这个数字是随时变化的,60,59,58,57....0,然后再次返回到 发送 按钮. 类似效果,可参考  360首 ...

  8. Xstream 学习地址

    http://forestqqqq.iteye.com/category/301129

  9. JSP学习——语法(二)

    1:JSP运行原理和九大隐式对象: 每个JSP 页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理.JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一 ...

  10. KMPlayer

    1. KMP 播放时,有声无图像,黑屏.解决: 打开KMP然后右键-选项-参数设置(或者进入KMP直接按F2)-视频处理-右边选择“渲染器”-在“渲染器”中选择“VMR9 未渲染 (HQ字幕)”-选中 ...