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 Stack<Integer> stack;
public MyDC2() {
stack = new Stack<Integer>();
}
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 Stack<Character> stack1;
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<Character>();
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<length;i++)
{
str=str+exper1[i];
}
//System.out.println(str);
return str;
}
/*public static void main(String[] args) {
String pp=null;
MyBC turner = new MyBC();
pp=turner.turn("( 1 + 2 ) * ( ( 8 - 2 ) / ( 7 - 4 ) )");
System.out.println(pp);
}*/
}
测试代码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 | 17.65% |
|设计 |30min | 17.65% |
|代码实现 |25min | 14.71% |
|测试 | 50min | 29.41% |
|分析总结 |35min | 20.59% |