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

20192318 實驗四 《資料結構與面向物件程式設計》實驗報告

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

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

1.實驗內容

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


以結對的方式完成Java密碼學相關內容的學習
(三)編寫有理數/複數計算器
結對程式設計,結對夥伴A編寫有理數計算器。結對夥伴B編寫複數計算器。
(四)遠端有理數計算器
結對程式設計,結對夥伴A程式設計實現客戶端,結果夥伴B實現伺服器端。
客戶端通過鍵盤輸入一個有理數計算的公式(例如:1/4 + 1/6 = ),並把該公式以字串的形式傳送給夥伴B(伺服器端),伺服器端根據字串計算出結果為5/12,並把結果返回給客戶端A,A收到結果後輸出結果。
(五)遠端複數計算器
客戶端通過鍵盤輸入一個複數計算的公式,並把該公式以字串的形式傳送給夥伴A(伺服器端),伺服器端根據字串計算出結果,並把結果返回給客戶端B,B收到結果後輸出結果。

2. 實驗過程及結果

(一)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(4567);
        //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="Hello!";
        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 {
        Socket socket = new Socket("192.168.1.241",4567);
        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,"GBK"));
        String info1 = " 使用者名稱:SXing,密碼:112233445566";
        String info = new String(info1.getBytes("GBK"),"GBK");
        printWriter.write(info);
        printWriter.flush();
        outputStreamWriter.write(info1);
        outputStreamWriter.flush();
        socket.shutdownOutput();
        String reply = null;
        while (!((reply = bufferedReader.readLine()) ==null)){
            System.out.println("接收伺服器的資訊為:" + reply);
        }
        bufferedReader.close();
        inputStream.close();
        outputStreamWriter.close();
        printWriter.close();
        outputStream.close();
        socket.close();
    }
}
  • 執行結果

(二)Java和密碼學










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

public class Rational
{
    public static void main (String[] args)
    {
        int n,m;
        char judge,count;
        Scanner scan = new Scanner (System.in);
        do
        {
            System.out.println ("please input +-*/%");
            count = scan.next().charAt(0);
            System.out.println ("please input n and m");
            n = scan.nextInt();
            m = scan.nextInt();
            switch (count)
            {
                case '+' :
                    System.out.println (n + "+" + m + "=" + (n+m));
                    break;
                case '-' :
                    System.out.println (n + "-" + m + "=" + (n-m));
                    break;
                case '*' :
                    System.out.println (n + "*" + m + "=" + (n*m));
                    break;
                case '/' :
                    System.out.println (n + "/" + m + "=" + (n/m));
                    break;
                case '%' :
                    System.out.println (n + "%" + m + "=" + (n%m));
                    break;
                default :
                    System.out.println ("error");
            }
            System.out.println ("do to y or leave to n ");
            judge = scan.next().charAt(0);
        }while(judge!='n');
    }
}
  • 執行結果

(四)遠端有理數計算器

  • 伺服器程式碼
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.StringTokenizer;


public class Server {

    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 {
        //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();
            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();
        //5.關閉資源
        printWriter.close();
    }
}
  • 客戶端程式碼
import java.io.*;
import java.net.Socket;
public class Long_Ration_Calculator
{
    public static void main(String[] args) throws IOException
    {
        Socket socket = new Socket("192.168.45.138",8809);
        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,"GBK"));
        String info1 = " 1/4 + 1/6";
        String info = new String(info1.getBytes("GBK"),"GBK");
        printWriter.write(info);
        printWriter.flush();
        outputStreamWriter.write(info1);
        outputStreamWriter.flush();
        socket.shutdownOutput();
        String reply = null;
        while (!((reply = bufferedReader.readLine()) ==null)){
            System.out.println("接收伺服器的資訊為:" + reply);
        }
        bufferedReader.close();
        inputStream.close();
        outputStreamWriter.close();
        printWriter.close();
        outputStream.close();
        socket.close();
    }
}
  • 建立分數類
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;
    }
}
  • 執行結果

(五)遠端複數計算器

  • 建立伺服器程式碼
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.StringTokenizer;

public class Server20192318 {

    private static Complex11 cplx1;
    private static Complex11 cplx2;
    private static String a,b;
    private static char ch;
    private static Complex11 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 Complex11(a);
            cplx2 = new Complex11(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 SocketClient1 {
    public static void main(String[] args) throws IOException {
        //1.建立客戶端Socket連線,指定伺服器位置和埠
        Socket socket = new Socket("192.168.45.138",8809);
//        Socket socket = new Socket("192.168.45.138",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,"GBK"));
        //3.利用流按照一定的操作,對socket進行讀寫操作
        String info1 = " 4.8 * 5.6";
//        String info = new String(info1.getBytes("GBK"),"GBK");
        //     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();
    }
}
  • 建立Complex11類
import java.util.StringTokenizer;

public class Complex11{
    private int RealPart;
    private int ImagePart;
    private char ch;

    //建構函式
    public Complex11(){}
    public Complex11(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 Complex11 ComplexAdd(Complex11 a){
        Complex11 b = new Complex11((this.RealPart+a.RealPart)+"."+(this.ImagePart+a.ImagePart));
        return b;
    }
    public Complex11 ComplexSub(Complex11 a){
        Complex11 b = new Complex11((this.RealPart-a.RealPart)+"."+(this.ImagePart-a.ImagePart));
        return b;
    }
    public Complex11 ComplexMulti(Complex11 a){
        Complex11 b = new Complex11((this.RealPart*a.RealPart-this.ImagePart*a.ImagePart)+"."+(this.ImagePart*a.RealPart+this.RealPart*a.ImagePart));
        return b;
    }
    public Complex11 ComplexDiv(Complex11 a){
        double scale = a.getRealPart()*a.getRealPart() + a.getImagePart()*a.getImagePart();
        Complex11 b = new Complex11((a.getRealPart() / scale)+"."+
                (- a.getImagePart() / scale));
        return b;
    }
}
  • 執行結果

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

  • 問題一:在第一個實驗中的伺服器以客戶端的傳輸資訊的時候客戶端總是在執行的時候程式執行失敗
  • 問題一解決方案:將結對雙方的網路連線在同一網路狀態下,把客戶端中的IP地址改變成為同一網路狀態下的IP地址即可執行成功
  • 問題二:在伺服器與客戶端傳輸結果中顯示為亂碼
  • 問題二解決方案:將程式中與下面的UTF-8均改變為GBK,就可以實現程式已中文形式輸出

實驗心得

  • 一個程式編寫到實現需要很多很多的步奏,也可能一個程式的實現需要很多行程式碼,常常會出現一些致命的錯誤,所以,在編寫相應的程式碼之前,要先想好每一步的具體步奏
  • 這次的程式碼有億點點多,億點點難度

參考資料