1. 程式人生 > 實用技巧 ># 20192324 2020-2021-1 《資料結構與面向物件程式設計》實驗四報告

# 20192324 2020-2021-1 《資料結構與面向物件程式設計》實驗四報告

課程:《程式設計與資料結構》
班級: 1923
姓名: 夏馨
學號:20192324
實驗教師:王志強
實驗日期:2020年10月26日
必修/選修: 必修

1.實驗內容

(一)Java Socket程式設計
1.學習藍墨雲上教材《Java和Android程式設計》“第16章 輸入/輸出 ”和“第22章 網路”,學習JavaSocket程式設計
2.結對程式設計。結對夥伴A編寫客戶端SocketClient.java,結對夥伴B編寫伺服器端。
3.截圖加學號水印上傳藍墨雲,程式碼push到碼雲,並撰寫實驗報告。
(二)Java和密碼學
參考 http://www.cnblogs.com/rocedu/p/6683948.html


以結對的方式完成Java密碼學相關內容的學習(帖子中所有程式碼和相關知識點需要學習)。提交學習成果碼雲連結和代表性成果截圖,要有學號水印。
(三)編寫有理數/複數計算器
結對程式設計,結對夥伴A編寫有理數計算器。結對夥伴B編寫複數計算器。截圖加水印上傳藍墨雲,程式碼push碼雲。
(四)遠端有理數計算器
結對程式設計,結對夥伴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),一個人不能僅實現客戶端,必須實現一個客戶端和伺服器,否則兩個實驗均不得分!!!

2. 實驗過程及結果

(1)Java Socket程式設計

  • 伺服器
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;

    public class Servertest {
    public static void main(String[] args) throws IOException {
      //1.建立一個伺服器Socket(ServerSocket)繫結指定埠
      ServerSocket serverSocket=new ServerSocket(1234);
      //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="Ture!!!";
      printWriter.write(reply);
      printWriter.flush();
      //5.關閉資源
      printWriter.close();
      outputStream.close();
      bufferedReader.close();
      inputStream.close();
      socket.close();
      serverSocket.close();
    

    }
    }

  • 客戶端
    import java.io.*;
    import java.net.Socket;

        public class SocketClient {
        public static void main(String[] args) throws IOException {
      //1.建立客戶端Socket連線,指定伺服器位置和埠
      Socket socket = new Socket("192.168.56.1",8800);
      // Socket socket = new Socket("192.168.43.55",8800);
    
      //2.得到socket讀寫流
      OutputStream outputStream = socket.getOutputStream();
             PrintWriter printWriter = new PrintWriter(outputStream);
      OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
      //輸入流
      InputStream inputStream = socket.getInputStream();
      BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
      //3.利用流按照一定的操作,對socket進行讀寫操作
      String info1 = " 使用者名稱:Billy,密碼:123456";
      String info = new String(info1.getBytes("GBK"),"utf-8");
           printWriter.write(info);
           printWriter.flush();
      outputStreamWriter.write(info1);
      outputStreamWriter.flush();
      socket.shutdownOutput();
      //接收伺服器的響應
      String reply = null;
      while (!((reply = bufferedReader.readLine()) ==null)){
          System.out.println("接收伺服器的資訊為:" + reply);
      }
      //4.關閉資源
      bufferedReader.close();
      inputStream.close();
      outputStreamWriter.close();
      //printWriter.close();
      outputStream.close();
      socket.close();
    

    }
    }

  • 執行結果

(二)JAVA和密碼學








(三)編寫有理數/複數計算器

  • 建立分數類
    import java.util.StringTokenizer;

public class Fraction {
int fenzi,fenmu;
char ch;

public Fraction(String str) {
    StringTokenizer st=new StringTokenizer(str,"/",true);
    this.fenzi = Integer.parseInt(st.nextToken());
    this.ch=st.nextToken().charAt(0);
    this.fenmu = Integer.parseInt(st.nextToken());
}

public Fraction yuefen(int fz,int fm){
    int i;

    for (i=2;i<=fz&&i<=fm;i++){
        if(fz%i==0&&fm%i==0){
            fz=fz/i;
            fm=fm/i;
        }
    }

    Fraction result=new Fraction(fz+"/"+fm);
    return result;
}

public Fraction getJia(Fraction x){
    int newFenmu=fenmu*x.fenmu;
    int newFenzi=fenzi*x.fenmu+x.fenzi*fenmu;
    return yuefen(newFenzi,newFenmu);
}

public Fraction getJian(Fraction x){
    int newFenmu=fenmu*x.fenmu;
    int newFenzi=fenzi*x.fenmu-x.fenzi*fenmu;
    return yuefen(newFenzi,newFenmu);
}

public Fraction getCheng(Fraction x){
    int newFenmu=fenmu*x.fenmu;
    int newFenzi=fenzi*x.fenzi;
    return yuefen(newFenzi,newFenmu);
}

public Fraction getChu(Fraction x){
    int newFenmu=fenmu*x.fenzi;
    int newFenzi=fenzi*x.fenmu;
    return yuefen(newFenzi,newFenmu);
}

@Override
public String toString() {
    return fenzi + "/" + fenmu;
}

}

  • 編寫計算器
    public class RationalNumberCalculator {
    public static void main(String[] args) {

      Fraction result;
      Fraction frac1,frac2;
      if(args[0].contains("/")){
          frac1=new Fraction(args[0]);
      }
      else{
          frac1=new Fraction(args[0]+"/"+1);
      }
    
      if(args[2].contains("/")){
          frac2=new Fraction(args[2]);
      }
      else{
          frac2=new Fraction(args[2]+"/"+1);
      }
    
      char ch=args[1].charAt(0);
    
    
      switch (ch)
      {
          case '+':
              result=frac1.getJia(frac2);
              System.out.println(frac1+String.valueOf(ch)+frac2+"="+result);
              break;
          case '-':
              result=frac1.getJian(frac2);
              System.out.println(frac1+String.valueOf(ch)+frac2+"="+result);
              break;
          case '*':
              result=frac1.getCheng(frac2);
              System.out.println(frac1+String.valueOf(ch)+frac2+"="+result);
              break;
          case '/':
              result=frac1.getChu(frac2);
              System.out.println(frac1+String.valueOf(ch)+frac2+"="+result);
              break;
          default:
              System.out.println("Illegal Input");
              break;
      }
    

    }
    }

  • 執行結果

(四)遠端有理數計算器

之前編寫過有理數和伺服器的程式碼,這裡可以直接用

  • 伺服器
    package Demo;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.StringTokenizer;

public class Server192324 {

private static Fraction frac2;
private static Fraction frac1;
private static String a,b;
private static char ch;
private static Fraction result = null;

public static void main(String[] args) throws IOException {
    ServerSocket serverSocket=new ServerSocket(4567);
    Socket socket=serverSocket.accept();
    InputStream inputStream=socket.getInputStream();
    BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(inputStream));
    OutputStream outputStream=socket.getOutputStream();
    PrintWriter printWriter=new PrintWriter(outputStream);
    String info=null;
    System.out.println("伺服器已經建立......");
    while(!((info = bufferedReader.readLine()) ==null)){
        System.out.println("我是伺服器,使用者資訊為:" + info);


        StringTokenizer st = new StringTokenizer(info, " ", false);
        a=st.nextToken();
        ch=st.nextToken().charAt(0);
        b=st.nextToken();
        frac1=new Fraction(a);
        frac2=new Fraction(b);

        switch (ch)
        {
            case '+':
                result=frac1.getJia(frac2);

                break;
            case '-':
                result=frac1.getJian(frac2);

                break;
            case '*':
                result=frac1.getCheng(frac2);

                break;
            case '/':
                result=frac1.getChu(frac2);

                break;
            default:

                break;
        }
    }


    String reply=frac1+String.valueOf(ch)+frac2+"="+result;
    printWriter.write(reply);
    printWriter.flush();

    printWriter.close();
    outputStream.close();
    bufferedReader.close();
    inputStream.close();
    socket.close();
    serverSocket.close();
}

}

  • 客戶端
    package Demo;

import java.io.*;
import java.net.Socket;

public class SocketClient2 {
public static void main(String[] args) throws IOException {
//1.建立客戶端Socket連線,指定伺服器位置和埠
Socket socket = new Socket("",4567);
// Socket socket = new Socket("172.16.43.187",8800);

    //2.得到socket讀寫流
    OutputStream outputStream = socket.getOutputStream();
    //       PrintWriter printWriter = new PrintWriter(outputStream);
    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
    //輸入流
    InputStream inputStream = socket.getInputStream();
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
    //3.利用流按照一定的操作,對socket進行讀寫操作
    String info1 = " 1/4 + 1/6";

// String info = new String(info1.getBytes("GBK"),"utf-8");
// printWriter.write(info);
// printWriter.flush();
outputStreamWriter.write(info1);
outputStreamWriter.flush();
socket.shutdownOutput();
//接收伺服器的響應
String reply = null;
while (!((reply = bufferedReader.readLine()) ==null)){
System.out.println("接收伺服器的資訊為:" + reply);
}
//4.關閉資源
bufferedReader.close();
inputStream.close();
outputStreamWriter.close();
//printWriter.close();
outputStream.close();
socket.close();
}
}

  • 執行結果

(五)遠端複數計算器

  • 複數類
    package Demo;
    import java.util.StringTokenizer;
    public class Complex{
    private int RealPart;
    private int ImagePart;
    private char ch;

    //建構函式
    public Complex(){}
    public Complex(String str){
    StringTokenizer st=new StringTokenizer(str,".",true);
    this.RealPart=Integer.parseInt(st.nextToken());
    this.ch=st.nextToken().charAt(0);
    this.ImagePart=Integer.parseInt(st.nextToken());
    }

    //返回
    public double getRealPart(){
    return RealPart;
    }

    public double getImagePart(){
    return ImagePart;
    }

    //接收
    public void setRealPart(int realPart){
    RealPart=realPart;
    }

    public void setImagePart(int imagePart){
    ImagePart=imagePart;
    }

    //重寫函式toString
    public String toString(){
    return RealPart + "." + ImagePart;
    }

    public boolean equals(Object a){
    if (a==this){
    return true;
    }
    else{
    return false;
    }
    }

    // 定義公有方法:加減乘除
    public Complex ComplexAdd(Complex a){
    Complex b = new Complex((this.RealPart+a.RealPart)+"."+(this.ImagePart+a.ImagePart));
    return b;
    }
    public Complex ComplexSub(Complex a){
    Complex b = new Complex((this.RealPart-a.RealPart)+"."+(this.ImagePart-a.ImagePart));
    return b;
    }
    public Complex ComplexMulti(Complex a){
    Complex b = new Complex((this.RealParta.RealPart-this.ImageParta.ImagePart)+"."+(this.ImageParta.RealPart+this.RealParta.ImagePart));
    return b;
    }
    public Complex ComplexDiv(Complex a){
    double scale = a.getRealPart()a.getRealPart() + a.getImagePart()a.getImagePart();
    Complex b = new Complex((a.getRealPart() / scale)+"."+
    (- a.getImagePart() / scale));
    return b;
    }
    }

  • 伺服器
    package Demo;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.StringTokenizer;

public class Server192324_1 {

private static Complex cplx1;
private static Complex cplx2;
private static String a,b;
private static char ch;
private static Complex result = null;

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


        StringTokenizer st = new StringTokenizer(info, " ", false);
        a = st.nextToken();
        ch = st.nextToken().charAt(0);
        b = st.nextToken();
        cplx1 = new Complex(a);
        cplx2 = new Complex(b);

        switch (ch) {
            case '+':
                result = cplx1.ComplexAdd(cplx2);

                break;
            case '-':
                result = cplx1.ComplexSub(cplx2);

                break;
            case '*':
                result = cplx1.ComplexMulti(cplx2);

                break;
            case '/':
                result = cplx1.ComplexDiv(cplx2);
                break;
            default:
                break;
        }
    }

    //給客戶一個響應
    String reply=cplx1+String.valueOf(ch)+cplx2+"="+result;
    printWriter.write(reply);
    printWriter.flush();
    //5.關閉資源
    printWriter.close();
    outputStream.close();
    bufferedReader.close();
    inputStream.close();
    socket.close();
    serverSocket.close();
}

}

  • 客戶端
    import java.io.*;
    import java.net.Socket;

public class SocketClient3 {
public static void main(String[] args) throws IOException {
//1.建立客戶端Socket連線,指定伺服器位置和埠
Socket socket = new Socket("",8809);
// Socket socket = new Socket("172.16.43.187",8800);

    //2.得到socket讀寫流
    OutputStream outputStream = socket.getOutputStream();
    //       PrintWriter printWriter = new PrintWriter(outputStream);
    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
    //輸入流
    InputStream inputStream = socket.getInputStream();
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
    //3.利用流按照一定的操作,對socket進行讀寫操作
    String info1 = " 4.8 * 5.6";

// String info = new String(info1.getBytes("GBK"),"utf-8");
// printWriter.write(info);
// printWriter.flush();
outputStreamWriter.write(info1);
outputStreamWriter.flush();
socket.shutdownOutput();
//接收伺服器的響應
String reply = null;
while (!((reply = bufferedReader.readLine()) ==null)){
System.out.println("接收伺服器的資訊為:" + reply);
}
//4.關閉資源
bufferedReader.close();
inputStream.close();
outputStreamWriter.close();
//printWriter.close();
outputStream.close();
socket.close();
}
}

  • 執行結果

3. 實驗過程中遇到的問題和解決過程

  • 問題1:結對伺服器和客戶端傳送資訊時總是飄紅
  • 問題1解決方案:cmd中找到自己的ip地址後輸入host中且連在一個wifi下解決了
  • 問題2:密碼學習比較困難
  • 問題2解決方案:參照連結的學習方法與自己網上搜索課外資料慢慢學習

其他(感悟、思考等)

  • java真的太難了,頭皮發麻
  • 至此實驗結束,java學習便告一段落了,自己可能學到的東西並沒有想象中的多,但還是都敲了一下程式碼,下網在下一階段的學習中能更認真努力一些。

參考資料