《数据结构与面向对象程序设计》实验三报告
课程:《程序设计与数据结构》
班级: 1923
姓名: 杨坤
学号:20192320
实验教师:王自强
实验日期:2020年10月8日
必修/选修: 必修
1.实验内容
(一)Java Socket编程
1.学习蓝墨云上教材《Java和Android编程》“第16章 输入/输出 ”和“第22章 网络”,学习JavaSocket编程
2.结对编程。结对伙伴A编写客户端SocketClient.java,结对伙伴B编写服务器端。
3.截图加学号水印上传蓝墨云,代码push到码云,并撰写实验报告。
//import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class server {
public static void main(String[] args) throws IOException {
//1.建立一个服务器Socket(ServerSocket)绑定指定端口
ServerSocket serverSocket=new ServerSocket(8809);
//2.使用accept()方法阻止等待监听,获得新连接
Socket socket=serverSocket.accept();
//3.获得输入流
InputStream inputStream=socket.getInputStream();
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(inputStream));
//获得输出流
OutputStream outputStream=socket.getOutputStream();
PrintWriter printWriter=new PrintWriter(outputStream);
//4.读取用户输入信息
String info=null;
System.out.println("服务器已经建立......");
while(!((info = bufferedReader.readLine()) ==null)){
System.out.println("我是服务器,用户信息为:" + info);
}
//给客户一个响应
String reply="welcome";
printWriter.write(reply);
printWriter.flush();
//5.关闭资源
printWriter.close();
outputStream.close();
bufferedReader.close();
inputStream.close();
socket.close();
serverSocket.close();
}
}
(二)Java和密码学
参考 http://www.cnblogs.com/rocedu/p/6683948.html
以结对的方式完成Java密码学相关内容的学习(帖子中所有代码和相关知识点需要学习)。提交学习成果码云链接和代表性成果截图,要有学号水印。
(三)编写有理数/复数计算器
结对编程,结对伙伴A编写有理数计算器。结对伙伴B编写复数计算器。截图加水印上传蓝墨云,代码push码云。
package Complex;
public class ComplexNumber
{
double Realpart;
double Imagepart;
public double getRealpart() {
return Realpart;
}
public double getImagepart() {
return Imagepart;
}
public void setRealpart(double realpart) {
Realpart = realpart;
}
public void setImagepart(double imagepart) {
Imagepart = imagepart;
}
public ComplexNumber()
{
}
public ComplexNumber(double realpart, double imagepart) {
Realpart = realpart;
Imagepart = imagepart;
}
@Override
public String toString() {
return "ComplexNumber{" +
"Realpart=" + Realpart +
", Imagepart=" + Imagepart +
'}';
}
}
package Complex;
public class ComplexNumCal extends ComplexNumber implements Comparable
{
public ComplexNumCal(double realpart, double imagepart)
{super(realpart,imagepart);}
public ComplexNumCal (){}
public ComplexNumCal add(ComplexNumCal a,ComplexNumCal b)
{
ComplexNumCal temp=new ComplexNumCal();
temp.Realpart=a.Realpart+b.Realpart;
temp.Imagepart=a.Imagepart+b.Imagepart;
return temp;
}
public ComplexNumCal contract(ComplexNumCal a,ComplexNumCal b)
{
ComplexNumCal temp=new ComplexNumCal();
temp.Realpart=a.Realpart-b.Realpart;
temp.Imagepart = a.Imagepart - b.Imagepart;
return temp;
}
public ComplexNumCal multi(ComplexNumCal a,ComplexNumCal b)
{
ComplexNumCal temp=new ComplexNumCal();
temp.Realpart = a.Realpart * b.Realpart - a.Imagepart * b.Imagepart;
temp.Imagepart = a.Realpart * b.Imagepart + a.Imagepart * b.Realpart;
return temp;
}
public ComplexNumCal div(ComplexNumCal a,ComplexNumCal b)
{
ComplexNumCal temp=new ComplexNumCal();
temp.Realpart = a.Realpart * b.Realpart - a.Imagepart * b.Imagepart;
temp.Imagepart = a.Realpart * b.Imagepart + a.Imagepart * b.Realpart;
return temp;
}
public int compareTo(ComplexNumCal o) {
Integer i=-5;
if((this.Realpart+this.Imagepart)<(o.Realpart+o.Imagepart))
i=-1;
else if((this.Realpart+this.Imagepart)==(o.Realpart+o.Imagepart))
i=0;
else if((this.Realpart+this.Imagepart)>(o.Realpart+o.Imagepart))
i=1;
return i;
}
@Override
public int compareTo(Object o) {
return 0;
}
}
有理数:
package myRocket;
import duotai.Pets;
public class RationNumber {
private int numerator,denominator;
public RationNumber(int numer,int denom)
{
if(denom==0)
denom=1;
if(denom<0)
{
numer=numer*-1;
denom=denom*-1;
}
numerator=numer;
denominator=denom;
}
public RationNumber(){}
public int getNumerator() {
return numerator;
}
public int getDenominator() {
return denominator;
}
public RationNumber reciprocal()
{
return new RationNumber(denominator, numerator);
}
public RationNumber add(RationNumber op2)
{
int commonDenominator=denominator*op2.getDenominator();
int numerator1=numerator*op2.getDenominator();
int numerator2=op2.getNumerator()*denominator;
int sum=numerator1+numerator2;
return new RationNumber(sum, commonDenominator);
}
public RationNumber subtract(RationNumber op2)
{
int commonDenominator=denominator*op2.getDenominator();
int numerator1=numerator*op2.getDenominator();
int numerator2=op2.getNumerator()*denominator;
int difference=numerator1-numerator2;
return new RationNumber(difference, commonDenominator);
}
public RationNumber multiply(RationNumber op2)
{
int numer=numerator*op2.getDenominator();
int denom=denominator*op2.getDenominator();
return new RationNumber(numer, denom);
}
public RationNumber divide(RationNumber op2)
{
return multiply(op2.reciprocal());
}
private void reduce()
{
if(numerator!=0)
{
int common=gcd(Math.abs(numerator),denominator);
numerator=numerator/common;
denominator=denominator/common;
}
}
private int gcd(int num1,int num2)
{
while (num1!=num2)
if(num1>num2)
num1=num1-num2;
else
num2=num2-num1;
return num1;
}
@Override
public String toString() {
return "RationNumber{" +
"numerator=" + numerator +
", denominator=" + denominator +
'}';
}
}
package myRocket;
import duotai.Pets;
public class RationNumber {
private int numerator,denominator;
public RationNumber(int numer,int denom)
{
if(denom==0)
denom=1;
if(denom<0)
{
numer=numer*-1;
denom=denom*-1;
}
numerator=numer;
denominator=denom;
}
public RationNumber(){}
public int getNumerator() {
return numerator;
}
public int getDenominator() {
return denominator;
}
public RationNumber reciprocal()
{
return new RationNumber(denominator, numerator);
}
public RationNumber add(RationNumber op2)
{
int commonDenominator=denominator*op2.getDenominator();
int numerator1=numerator*op2.getDenominator();
int numerator2=op2.getNumerator()*denominator;
int sum=numerator1+numerator2;
return new RationNumber(sum, commonDenominator);
}
public RationNumber subtract(RationNumber op2)
{
int commonDenominator=denominator*op2.getDenominator();
int numerator1=numerator*op2.getDenominator();
int numerator2=op2.getNumerator()*denominator;
int difference=numerator1-numerator2;
return new RationNumber(difference, commonDenominator);
}
public RationNumber multiply(RationNumber op2)
{
int numer=numerator*op2.getDenominator();
int denom=denominator*op2.getDenominator();
return new RationNumber(numer, denom);
}
public RationNumber divide(RationNumber op2)
{
return multiply(op2.reciprocal());
}
private void reduce()
{
if(numerator!=0)
{
int common=gcd(Math.abs(numerator),denominator);
numerator=numerator/common;
denominator=denominator/common;
}
}
private int gcd(int num1,int num2)
{
while (num1!=num2)
if(num1>num2)
num1=num1-num2;
else
num2=num2-num1;
return num1;
}
@Override
public String toString() {
return "RationNumber{" +
"numerator=" + numerator +
", denominator=" + denominator +
'}';
}
}
(四)远程有理数计算器
结对编程,结对伙伴A编程实现客户端,结果伙伴B实现服务器端。
客户端通过键盘输入一个有理数计算的公式(例如:1/4 + 1/6 = ),并把该公式以字符串的形式发送给伙伴B(服务器端),服务器端根据字符串计算出结果为5/12,并把结果返回给客户端A,A收到结果后输出结果。截图加水印上传蓝墨云,代码push码云。
(五)远程复数计算器
结对编程,结对伙伴B编程实现客户端,结果伙伴A实现服务器端。
客户端通过键盘输入一个有理数计算的公式(例如:1/4 + 1/6 = ),并把该公式以字符串的形式发送给伙伴A(服务器端),服务器端根据字符串计算出结果为5/12,并把结果返回给客户端B,B收到结果后输出结果。截图加水印上传蓝墨云,代码push码云。
注意实验四(4)和实验四(5),一个人不能仅实现客户端,必须实现一个客户端和服务器,否则两个实验均不得分!!!
package myRocket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
public class 客户端初步尝试 {
public static void main(String[] args) throws IOException {
String host = "127.0.0.1";
int port = 8080;
//Socket socket = new Socket(host, port);
//OutputStream output = socket.getOutputStream();
Scanner scan = new Scanner(System.in);
String message=new String();
while(true){
Socket socket = new Socket(host, port);
OutputStream output = socket.getOutputStream();
System.out.println("输入信息");
message=scan.next();
output.write(message.getBytes("utf-8"));
socket.shutdownOutput();
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String read = input.readLine();
System.out.println("服务器的内容 " +read);
input.close();
if(message.equals("end")) break;
}
//message="1/4+1/3";
//output.write(message.getBytes("utf-8"));
//正常来说,客户端打开一个输出流,如果不做约定,也不关闭它,那么服务端永远不知道客户端是否发送完消息,
//那么服务端会一直等待下去,直到读取超时。所以怎么告知服务端已经发送完消息就显得特别重要。
//socket.close();
//Socket关闭的时候,服务端就会收到响应的关闭信号,那么服务端也就知道流已经关闭了,这个时候读取操作完成,就可以继续后续工作
}
}
package myRocket;
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class 服务器初步尝试 {
public static void main(String[] args) throws Exception{
//指定监听的端口
int myport = 8080;
ServerSocket myserver = new ServerSocket(myport,1);
//等待连接的到来
//System.out.println("server将一直等待连接的到来");
//Socket socket = myserver.accept();
//accept 侦听并接受到此套接字的连接。此方法在连接传入之前一直阻塞。
//即 服务器调用 accept() 方法,该方法将一直等待直到客户端连接到服务器上给定的端口。.
// 读取客户端数据
//BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String clientInputStr =new String();
while(true) {
//等待连接的到来
System.out.println("server将一直等待连接的到来");
Socket socket = myserver.accept();
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
clientInputStr = input.readLine();
/*Scanner scan = new Scanner(socket.getInputStream());
clientInputStr = scan.next();//这也是一种方法*/
System.out.println("客户端发过来的内容:" + clientInputStr);
if(clientInputStr.equals("end")) {input.close();break;}
OutputStream output = socket.getOutputStream();
output.write(复数计算/*有理数计算尝试*/.计算(clientInputStr).getBytes());
input.close();
output.close();
}
//public InputStream getInputStream()throws IOException返回此套接字的输入流。
//------------------------------------
// public BufferedReader(Reader in) :创建一个使用默认大小输入缓冲区的缓冲字符输入流。
//InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset ***读取字节并将其解码为字符*** 。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
//每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。
//为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。例如:
// BufferedReader in
// = new BufferedReader(new InputStreamReader(System.in));
//字节流->字符流->字符流缓冲区
//-----------------------------------
//String clientInputStr = input.readLine();//这里要注意和客户端输出流的写方法对应,否则会抛 EOFException
// 处理客户端数据
//System.out.println("客户端发过来的内容:" + clientInputStr);
//有理数计算尝试.计算(clientInputStr);
//input.close();
//socket.close();
myserver.close();
}
}
2.实验心得体会
自身的自学能力还要提升,大多数的实验代码都在同学的帮助下完成,在运到困难时,容易感到沮丧,还要多锻炼自己。平时也要多加练习。
实现Socket时,每次close后都要重新连接一次,才能继续使用。