JAVA學習線路:day14-網路程式設計

CodeBull發表於2020-11-04

心得:
我是一名正在自學的java的即將畢業的大學生
總結筆記是為了讓自己更好的理解和加深印象。可能不是那麼美觀,自己可以看懂就好
所有的文件和原始碼都開源在GitHub: https://github.com/kun213/JavaNotes上了。希望我們可以一起加油,一起學習,一起交流

day14 【網路程式設計】

@

一、網路程式設計入門

1.1 可以說出軟體的結構

C/S結構 :全稱為Client/Server結構,是指客戶端和伺服器結構。常見程式有QQ、迅雷等軟體。

B/S結構 :全稱為Browser/Server結構,是指瀏覽器和伺服器結構。常見瀏覽器有谷歌、火狐等。

1.2 可以說出UDP和TCP協議特點

  • TCP:傳輸控制協議 (Transmission Control Protocol)。TCP協議是面向連線的通訊協議,即傳輸資料之前,在傳送端和接收端建立邏輯連線,然後再傳輸資料,它提供了兩臺計算機之間可靠無差錯的資料傳輸。
    • 三次握手:TCP協議中,在傳送資料的準備階段,客戶端與伺服器之間的三次互動,以保證連線的可靠。
      • 第一次握手,客戶端向伺服器端發出連線請求,等待伺服器確認。
      • 第二次握手,伺服器端向客戶端回送一個響應,通知客戶端收到了連線請求。
      • 第三次握手,客戶端再次向伺服器端傳送確認資訊,確認連線。整個互動過程如下圖所示

完成三次握手,連線建立後,客戶端和伺服器就可以開始進行資料傳輸了。由於這種面向連線的特性,TCP協議可以保證傳輸資料的安全,所以應用十分廣泛,例如下載檔案、瀏覽網頁等。

  • UDP:使用者資料包協議(User Datagram Protocol)。UDP協議是一個面向無連線的協議。傳輸資料時,不需要建立連線,不管對方端服務是否啟動,直接將資料、資料來源和目的地都封裝在資料包中,直接傳送。每個資料包的大小限制在64k以內。它是不可靠協議,因為無連線,所以傳輸速度快,但是容易丟失資料。日常應用中,例如視訊會議、QQ聊天等。

    每次傳送的資料最大為64kb。

二、TCP通訊協議

2.1 可以說出TCP協議下兩個常用類名稱

在Java中,提供了兩個類用於實現TCP通訊程式:

  • 客戶端:java.net.Socket 類表示。建立Socket物件,向服務端發出連線請求,服務端響應請求,兩者建立連線開始通訊。
  • 服務端:java.net.ServerSocket 類表示。建立ServerSocket物件,相當於開啟一個服務,並等待客戶端的連線。

2.2 如何編寫TCP協議下字串資料傳輸程式

實現TCP通訊的客戶端程式:

/**
 * 實現TCP通訊的客戶端程式
 *
 * java.net.Socket 實現客戶端的套接字物件,連線物件
 *
 * 需求: 客戶端程式和伺服器程式實現資料交換
 *
 * 實現步驟:
 *   1: 建立Socket物件 (主動連線伺服器)
 *        Socket(String host, int port)
 *
 *   2: OutputStream getOutputStream()
 *      返回套接字中的位元組輸出流
 *      方法write寫入資料, 寫到伺服器
 *
 *   3: InputStream getInputStream()
 *      返回套接字中的位元組輸入流
 *       方法read讀取資料,讀取的是伺服器發回來的資料
 *
 *   4: 釋放資源
 */
public class TCPClient {
    public static void main(String[] args)throws IOException {
        //建立Socket物件 (主動連線伺服器)
        Socket socket = new Socket("127.0.0.1",9000);

        //OutputStream getOutputStream()
        OutputStream out = socket.getOutputStream();
        //位元組流的方法寫資料
        out.write("你好伺服器".getBytes());//沒有寫到檔案中,寫到了伺服器中

        InputStream  in = socket.getInputStream();//獲取位元組輸入流
        byte[] bytes = new byte[1024];
        int len = in.read(bytes);//客戶端輸入流,讀取到伺服器發回來的資料
        System.out.println(new String(bytes,0,len));

        //釋放資源
        //out.close();
        socket.close();
    }
}

實現TCP通訊的伺服器程式:

/**
 * 實現TCP通訊的伺服器程式
 * 192.168.27.95
 * java.net.ServerSocket 實現TCP協議中的伺服器套接字物件
 *
 * 實現TCP伺服器程式步驟:
 *   1: 建立ServerSocket物件
 *     ServerSocket(int port) 埠號
 *
 *   2: 等待客戶端的連線,如果沒有客戶端連線,永遠等待
 *     ServerSocket類方法 accept()同意
 *     方法 accept()返回值是 Socket物件 (客戶端的連線物件,包含客戶端的IP)
 *
 *   3: Socket物件中獲取到位元組輸出流
 *     OutputStream getOutputStream()
 *     方法write寫資料,寫到客戶端
 *
 *   4: Socket物件中獲取到位元組輸入流
 *     InputStream getInputStream()
 *     方法read讀取資料,讀取的是客戶端發來資料
 *
 *   5: 釋放資源
 */
public class TCPServer {
    public static void main(String[] args)throws IOException {
        //建立ServerSocket物件
        ServerSocket server = new ServerSocket(9000);
        //ServerSocket類方法 accept()同意
        Socket socket = server.accept();
        //System.out.println(socket);

        //使用客戶端連線獲取物件,輸入流
        InputStream in = socket.getInputStream();
        //in輸入流的方法read()讀取客戶端發來資料
        byte[] bytes = new byte[1024];
        //len返回的是讀取到的位元組個數
        int len = in.read(bytes);
        System.out.println(new String(bytes,0,len));

        //Socket客戶端物件,獲取位元組輸出流
        OutputStream out = socket.getOutputStream();
        out.write("收到!".getBytes());//伺服器輸出流,寫回客戶端

        //釋放資源
        socket.close();
        server.close();
    }
}

2.3 理解TCP協議下檔案上傳案例

實現圖片上傳客戶端:

/**
 * 實現TCP圖片上傳客戶端
 * 實現步驟:
 *  1: 建立Socket物件,連線伺服器
 *  2: FileInputStream讀取 mm.jpg   位元組陣列
 *  3: Socket物件獲取位元組輸出流
 *     位元組陣列,交給輸出流,寫到伺服器
 *  4: Socket物件獲取位元組輸入流
 *     全部的圖片傳送完畢
 *     輸入流,讀取伺服器回來的提示資訊 "上傳成功"
 *
 *     客戶端方法Socket: shutdownOutput() 終止連線物件的輸出流 ,
 *     同時跟上TCP終止序列
 *  5: 釋放資源
 */
public class TCPClient {
    public static void main(String[] args) throws IOException{
        //1: 建立Socket物件,連線伺服器
        Socket socket = new Socket("127.0.0.1",9000);
        //2: 自己的位元組輸入流,讀取圖片mm.jpg
        FileInputStream fis = new FileInputStream("e:/msh.jpg");
        //3: Socket物件獲取位元組輸出流
        OutputStream out = socket.getOutputStream();//任何資料,寫向伺服器
        byte[] bytes = new byte[1024];
        int len = 0;
        //fis讀取檔案末尾,JVM返回read() -1
        while ((len = fis.read(bytes))!=-1){
            out.write(bytes,0,len);
        }
        //告訴伺服器,沒資料了,別讀,伺服器傳送TCP的終止符
        socket.shutdownOutput();
        //4:Socket物件獲取位元組輸入流
        InputStream in = socket.getInputStream();//輸入流,讀取伺服器回來的資料
        len = in.read(bytes);
        System.out.println("伺服器提示::"+new String(bytes,0,len));

        socket.close();
    }
}

實現圖片上傳伺服器端:

/**
 * 實現圖片上傳伺服器端
 * 實現步驟:
 *  1: 建立物件ServerSocket 繫結埠
 *  2: Socket accept()方法等待客戶端連線
 *  3: Socket物件,獲取位元組輸入流,讀取客戶端發來圖片的位元組
 *  4: 建立位元組輸出流,讀取到圖片,寫到 e:/upload
 *  5: Socket物件,獲取位元組輸出流,"上傳成功"寫回客戶端
 *
 *  bug:
 *    1: 演示了2次,為什麼資料夾中只有一個檔案,同名覆蓋
 *      a: 1.jpg
 *      b: 1.jpg
 *
 *   2: 客戶端收不到伺服器的上傳成功
 //告訴伺服器,沒資料了,別讀,伺服器傳送TCP的終止符
 */
public class TCPServer {
    public static void main(String[] args) throws IOException{
        //1: 建立物件ServerSocket 繫結埠
        ServerSocket server = new ServerSocket(9000);
        // 2: Socket accept()方法等待客戶端連線
        Socket socket = server.accept();
        //3: Socket物件,獲取位元組輸入流,讀取客戶端發來圖片的位元組
        InputStream in = socket.getInputStream();
        //4: 建立位元組輸出流,讀取到圖片,寫到 e:/upload
        //上傳的檔案,重新命名,獲取當前日期 轉換成字串
        String filename = new SimpleDateFormat("yyyyMMddHHmmssssss").format(Calendar.getInstance().getTime())+".jpg";
        FileOutputStream fos = new FileOutputStream("e:/upload/"+filename);
        byte[] bytes = new byte[1024];
        int len = 0;
        //read()讀取是客戶端寫來的圖片!!
        while ( (len = in.read(bytes))!=-1){
            fos.write(bytes,0,len);
        }

        //5: Socket物件,獲取位元組輸出流,"上傳成功"寫回客戶端
        OutputStream out= socket.getOutputStream();
        out.write("上傳成功!".getBytes());

        socket.close();
        server.close();
    }
}

這是我的公眾號,希望大家可以關注,讓我們一起做最好的自我。
我也會把我自學視訊分享在上面,供大家一起學習。

CodeBull

相關文章