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. Zookeeper未授权访问

    l 漏洞名称: zookeeper未授权访问 l  漏洞影响版本: zookeeper l  漏洞细节: ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubb ...

  2. Python入门-多行语句

    1. Python语句中一般以新行作为为语句的结束符. 但是我们可以使用斜杠( \)将一行的语句分为多行显示. 2. 语句中包含[], {} 或 () 括号就不需要使用多行连接符. days = [' ...

  3. python进程、线程、协程(转载)

    python 线程与进程简介 进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资 ...

  4. mysql概要(七)表字段管理,字段的增删改

    1.添加列 放在某列之后 放第一列: 2.修改(声明和名字),删除列 2.1修改声明 2.2删除列

  5. BigTale

    Google's BigTable 原理 (翻译)     题记:google 的成功除了一个个出色的创意外,还因为有 Jeff Dean 这样的软件架构天才.                     ...

  6. (二)再议MII、RMII、GMII接口

    概述:         MII (Media Independent Interface(介质无关接口)或称为媒体独立接口,它是IEEE-802.3定义的以太网行业标准.它包括一个数据接口和一个MAC ...

  7. N-Queens II

    Description: Follow up for N-Queens problem. Now, instead outputting board configurations, return th ...

  8. STM32学习笔记(一) 如何新建一个STM32工程模板

    学习stm32,第一步就是选择开发工具了,GCC,MDK,IAR每一种都有自己的优劣势,这里我选择使用MDK软件实现STM32模板.当然如果想更快的接触stm32实例,领略嵌入式开发的魅力,STM也提 ...

  9. CodeForces 429 B Working out(递推dp)

    题目连接:B. Working out 我想了很久都没有想到怎么递推,看了题解后试着自己写,结果第二组数据就 wa 了,后来才知道自己没有判选择的两条路径是否只是一个交点. 大概思路是:先预处理出每个 ...

  10. C++——string类和标准模板库

    一.string类 1.构造函数 string实际上是basic_string<char>的一个typedef,同时省略了与内存管理相关的参数.size_type是一个依赖于实现的整型,是 ...