20155328 实验五 网络编程与安全
实验目的
1.了解计算机网络基础
2.掌握JavaSocket编程
3.理解混合密码系统
4.掌握Java密码技术相关API的使用
实验内容
任务一
内容:编程实现中缀表达式转后缀表达式的功能 MyBC.java,并实现从上面功能中获取的表达式中实现后缀表达式求值的功能,调用MyDC.java
代码如下:
MyDC2:
package experiment5;import java.util.StringTokenizer;import java.util.Stack;/** * Created by lxkj on 2017/6/1. */public class MyDC2{ // constant for addition symbol */ private final char ADD = '+'; // constant for subtraction symbol */ private final char SUBTRACT = '-'; // constant for multiplication symbol */ private final char MULTIPLY = '*'; // constant for division symbol */ private final char DIVIDE = '/'; // the stack */ private Stackstack; public MyDC2() { stack = new Stack (); } public int evaluate (String expr) { int op1, op2, result = 0; String token; StringTokenizer tokenizer = new StringTokenizer (expr); while (tokenizer.hasMoreTokens()) { token = tokenizer.nextToken(); //如果是运算符,调用isOperator if (isOperator(token)) { //从栈中弹出操作数 //op2 =Integer.parseInt(stack.pop()); op2 =stack.pop(); //从栈中弹出操作数 //op1 =Integer.parseInt(stack.pop()); op1 =stack.pop(); //根据运算符和两个操作数调用evalSingleOp计算result; result = evalSingleOp(token.charAt(0),op1,op2); //计算result入栈; stack.push(result); } else//如果是操作数 //操作数入栈; stack.push(Integer.parseInt(token)); } return result; } private boolean isOperator (String token) { return ( token.equals("+") || token.equals("-") || token.equals("*") || token.equals("/") ); } private int evalSingleOp (char operation, int op1, int op2) { int result = 0; switch (operation) { case ADD: result = op1 + op2; break; case SUBTRACT: result = op1 - op2; break; case MULTIPLY: result = op1 * op2; break; case DIVIDE: result = op1 / op2; } return result; }}
MyBC:
import java.util.Stack;import java.util.StringTokenizer;/** * Created by lxkj on 2017/6/2. */public class MyBC{ private Stackstack1; public char Precede(char a,char b) { if(a=='#') if(b!='#') return '<'; else return '='; if(a==')') return '>'; if(a=='(') if(b!=')') return '<'; else return '='; if(a=='/'||a=='*') if(b!='(') return '>'; else return '<'; if(a=='-'||a=='+') if(b!='*'&&b!='/'&&b!='(') return '>'; else return '<'; return '>'; } public MyBC() { stack1 = new Stack (); stack1.push('#'); } public String turn(String expr) { int result = 0; String token; char topelem,optr; char[] exper1 = new char[100]; int i = 0; StringTokenizer tokenizer = new StringTokenizer (expr); /*while (tokenizer.hasMoreTokens()) { System.out.println(tokenizer.nextToken()); }*/ while (tokenizer.hasMoreTokens()) { token = tokenizer.nextToken(); //如果是运算符,调用isOperator if (isOperator(token)) { //调用Precede比较优先级 topelem=stack1.peek(); optr = token.charAt(0); if(Precede(topelem,optr)=='<') { stack1.push(optr); } else if(Precede(topelem,optr)=='=') { /*if(optr==')'){ optr=stack1.pop(); while(optr!='('){ exper1[i++]=optr; exper1[i++]=' '; optr=stack1.pop(); } }*/ optr =stack1.pop(); exper1[i++] = optr; exper1[i++] = ' '; } else if(Precede(topelem,optr)=='>') { optr =stack1.pop(); //从运算符栈中退出栈顶元素并放入后缀表达式exper1 exper1[i++] = optr; exper1[i++] = ' '; } }//如果是(则入栈 else if(token.equals("(")) { optr = token.charAt(0); stack1.push(optr); }//如果是)则退栈直到出现第一个( else if(token.equals(")")) { optr = stack1.pop(); while(optr!='(') { exper1[i++] = optr; exper1[i++] = ' '; optr = stack1.pop(); } } else//如果是操作数 //操作数放入后缀表达式exper1 { optr = token.charAt(0); //System.out.println(optr); exper1[i++]=optr; exper1[i++] = ' '; } } while(!stack1.isEmpty()) { optr = stack1.pop(); if(optr!='#'){ exper1[i++] = optr; exper1[i++] = ' '; } } //System.out.println(exper1); return ToString(exper1); } //@Override private boolean isOperator(String token) { return (token.equals("+") || token.equals("-") ||token.equals("*") || token.equals("/") ); } public static String ToString(char[] exper1){ int length = exper1.length; String str=" "; for(int i=0;i
测试代码MyBCTest如下:
package experiment5;import java.util.Scanner;import static org.junit.Assert.*;/** * Created by lxkj on 2017/6/2. */import java.util.Scanner;public class MyBCTest { public static void main (String[] args) { String expression1=null,expression2=null, again=null; int result,i=0,length=0; try { Scanner in = new Scanner(System.in); do { MyDC2 evaluator = new MyDC2(); MyBC turner = new MyBC(); System.out.println ("Enter a valid midfix expression: "); expression1 = in.nextLine(); //System.out.println(expression1); expression2 = turner.turn(expression1); while(expression2.charAt(i)!='\0'){ length++; i++; } //length 表示字符串包括‘\0’的字符个数 expression2 = expression2.substring(1,length-1); //System.out.println(expression2); result = evaluator.evaluate (expression2); System.out.println(); System.out.println ("That expression equals " + result); System.out.print ("Evaluate another expression [Y/N]? "); again = in.nextLine(); System.out.println(); } while (again.equalsIgnoreCase("y")); } catch (Exception e) { e.printStackTrace(); } }}
运行截图如下:
任务二
- 内容:
1.基于Java Socket实现客户端/服务器功能,传输方式用TCP
2.客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式通过网络发送给服务器
3.服务器接收到后缀表达式,调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
4.客户端显示服务器发送过来的结果
- 代码
服务器代码如下:
服务器代码:
package experiment5;import java.io.BufferedReader;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.InputStreamReader;import java.net.ServerSocket;import java.net.Socket;/** * Created by lxkj on 2017/6/2. */public class Server { public static final int PORT = 12345;//监听的端口号 public static void main(String[] args) { System.out.println("服务器启动...\n"); Server server = new Server(); server.init(); } public void init() { try { ServerSocket serverSocket = new ServerSocket(PORT); while (true) { // 一旦有堵塞, 则表示服务器与客户端获得了连接 Socket client = serverSocket.accept(); // 处理这次连接 new HandlerThread(client); } } catch (Exception e) { System.out.println("服务器异常: " + e.getMessage()); } } private class HandlerThread implements Runnable { private Socket socket; public HandlerThread(Socket client) { socket = client; new Thread(this).start(); } public void run() { try { // 读取客户端数据 DataInputStream input = new DataInputStream(socket.getInputStream()); String clientInputStr = input.readUTF();//这里要注意和客户端输出流的写方法对应,否则会抛 EOFException // 处理客户端数据 System.out.println("客户端发过来的内容:" + clientInputStr); MyDC2 evalute = new MyDC2(); int result = evalute.evaluate(clientInputStr); // 向客户端回复信息 DataOutputStream out = new DataOutputStream(socket.getOutputStream()); System.out.print("计算结果:\t"); // 发送键盘输入的一行 //String s = new BufferedReader(new InputStreamReader(System.in)).readLine(); out.writeUTF(String.valueOf(result)); out.close(); input.close(); } catch (Exception e) { System.out.println("服务器 run 异常: " + e.getMessage()); } finally { if (socket != null) { try { socket.close(); } catch (Exception e) { socket = null; System.out.println("服务端 finally 异常:" + e.getMessage()); } } } } }}
客户端代码如下:
package experiment5;import java.io.BufferedReader;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.net.Socket;/** * Created by lxkj on 2017/6/2. */public class Client { public static final String IP_ADDR = "127.0.0.1";//服务器地址 public static final int PORT = 12345;//服务器端口号 public static void main(String[] args) { System.out.println("客户端启动..."); System.out.println("当接收到服务器端字符为 \"OK\" 的时候, 客户端将终止\n"); while (true) { Socket socket = null; try { socket = new Socket(IP_ADDR, PORT); DataInputStream input = new DataInputStream(socket.getInputStream()); DataOutputStream out = new DataOutputStream(socket.getOutputStream()); System.out.print("请输入: \t"); String str = new BufferedReader(new InputStreamReader(System.in)).readLine(); MyBC turner = new MyBC(); String str1 = turner.turn(str); int length=0,i=0; while(str1.charAt(i)!='\0'){ length++; i++; } String str2 = str1.substring(1,length-1); out.writeUTF(str2); String ret = input.readUTF(); System.out.println("服务器端返回过来的是: " + ret); out.close(); input.close(); } catch (Exception e) { System.out.println("客户端异常:" + e.getMessage()); } finally { if (socket != null) { try { socket.close(); } catch (IOException e) { socket = null; System.out.println("客户端 finally 异常:" + e.getMessage()); } } } } }}
运行截图如下:
任务三
- 内容:
1.基于Java Socket实现客户端/服务器功能,传输方式用TCP
2.客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密后通过网络把密文发送给服务器
3.服务器接收到后缀表达式表达式后,进行解密(和客户端协商密钥,可以用数组保存),然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
4.客户端显示服务器发送过来的结果
运行截图:
任务四
- 内容:
1.基于Java Socket实现客户端/服务器功能,传输方式用TCP
2.客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文发送给服务器
3.客户端和服务器用DH算法进行3DES或AES算法的密钥交换
4.服务器接收到后缀表达式表达式后,进行解密,然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
5.客户端显示服务器发送过来的结果
运行截图
任务五
- 内容:
1.基于Java Socket实现客户端/服务器功能,传输方式用TCP
2.客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文和明文的MD5値发送给服务器
3.客户端和服务器用DH算法进行3DES或AES算法的密钥交换
4.服务器接收到后缀表达式表达式后,进行解密,解密后计算明文的MD5值,和客户端传来的MD5进行比较,一致则调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
5.客户端显示服务器发送过来的结果
运行截图
实验时间分配
步骤 | 耗时 |
---|---|
需求分析 | 30min |
设计 | 30min |
代码实现 | 25min |
测试 | 50min |
分析总结 | 35min |