筆記三、綜合案例

第三章、綜合案例

3.1 文件上傳案例

原理:客戶端讀取本地的文件,把文件上傳到服務器,服務器把上傳的文件保存到服務器的硬盤上

  • 客戶端使用本地的字節輸入流,讀取要上傳的文件

  • 客戶端使用網絡字節輸出流,把讀取到的文件上傳到服務器

  • 服務器使用網絡字節輸入流,讀取客戶端上傳的文件

  • 服務器使用本地的字節輸出流,把讀取到的文件保存到服務器的硬盤上

  • 服務器使用網絡字節輸出流,給客戶端回寫一個“上傳成功”

  • 客戶端使用網絡字節輸入流讀取服務器回寫的數據

  • 釋放資源

注意:

客戶端和服務器和本地硬盤進行讀寫,需要使用自己創建的字節流對象(本地流)
客戶端和服務器之間進行讀寫,必須使用Socket中提供的字節流對象(網絡流)

文件上傳的原理,就是文件的複製

明確:
	數據源
	數據目的地

文件上傳優化

  • 文件名稱寫死:創建文件使用不同名字

  • 循環接受問題:始終開啓Server,不斷接受文件

  • 效率問題:多線程解決

服務器代碼:


/**
 * 文件上傳案例服務器:讀取客戶端上傳的文件,保存到服務器的硬盤,給客戶端回寫"上傳成功"
 */
public class TCPServer {

    public static void main(String[] args) throws IOException {

        //1、創建一個服務器ServerSocket對象,和系統要指定的端口號
        ServerSocket server = new ServerSocket(8888);
        //2、使用ServerSocket對象中的方法accept獲取到請求的客戶端Socket對象

        /*
         * 讓服務器一直處於監聽狀態
         */
        while (true){
            Socket socket = server.accept();

            /*
             * 使用多線程,上傳一次文件創建一個線程
             */
            new Thread(new Runnable() {
                @Override
                public void run() {

                    try{
                        //3、使用Socket對象中的方法getInputSteam,獲取到網絡字節輸入流InputSteam對象
                        InputStream is = socket.getInputStream();
                        //4、判斷服務器硬盤上upload文件夾是否存在,不存在則創建
                        File file = new File("/Users/cwq/IdeaProjects/Net/src/upload");
                        if(!file.exists()){
                            file.mkdir();
                        }
                        //5、創建本地字節輸出流對象FileOutputStream,構造方法中綁定要輸出的目的地
                        /*
                         * 自定義命名規則:域名+毫秒值+隨機數
                         	jpg文件前需要加/
                         */
                        //FileOutputStream fos = new FileOutputStream(file + "/1.jpg");
                        String filename = "cwq" + System.currentTimeMillis() + new Random().nextInt() + ".jpg";
                        FileOutputStream fos = new FileOutputStream(file + "/" + filename);
                        //6、使用網絡字節輸入流InputSteam的方法read讀取客戶端上傳的文件
                        int len = 0;
                        byte[] bytes = new byte[1024];
                        while((len = is.read(bytes))!=-1){
                            //7、使用本地字節輸出流對象中的方法write把讀取到的文件保存到服務器的硬盤上
                            fos.write(bytes,0,len);
                        }
                        //8、使用Socket對象中的方法getOutputSteam,獲取到網絡字節輸出流OutputSteam對象
                        //9、使用網絡字節輸出流OutputSteam對象的write方法給客戶端回寫"上傳成功"
                        socket.getOutputStream().write("上傳成功".getBytes());
                        //10、釋放資源(FileOutputStream,Socket,ServerSocket)
                        fos.close();
                        socket.close();
                    }catch (IOException e){
                        System.out.println(e);
                    }
                }
            }).start();
        }
        //server.close();
    }
}

客戶端代碼

/**
 * 文件上傳案例的客戶端:讀取本地文件,上傳到服務器,讀取服務器回寫的數據
 */
public class TCPClient {

    public static void main(String[] args) throws IOException {

        //1、創建一個本地字節輸入流FileInputStream對象,構造方法中綁定要讀取的數據源
        FileInputStream fis = new FileInputStream("/Users/cwq/IdeaProjects/Net/src/image/1.jpg");
        //2、創建一個客戶端Socket對象,構造方法中綁定服務器的IP地址和端口號
        Socket socket = new Socket("127.0.0.1",8888);
        //3、使用Socket中的方法getOutputStream,獲取網絡字節輸出流OutputStream對象
        OutputStream os = socket.getOutputStream();
        //4、使用本地字節輸入流FileInputStream對象中方法read,讀取本地文件
        int len = 0;
        byte[] bytes = new byte[1024];
        while ((len = fis.read(bytes))!=-1){
            //5、使用網絡字節輸出流OutputStream對象中的方法write,把讀取到的文件上傳到服務器
            os.write(bytes,0,len);
        }

        /**
         * read方法讀取不到-1。導致阻塞,while進入死循環
         * 解決:上傳完文件,給服務器一個結束標記
         * void shutdownOutput() 禁止此套接字的輸出流
         * 對於TCP套接字,任何以前寫入的數據都將被髮送,並且後跟TCP的正常連接終止序列
         */
        socket.shutdownOutput();

        //6、使用Socket中的方法getInputStream,獲取網絡字節輸入流InputStream對象
        InputStream is = socket.getInputStream();
        //7、使用網絡字節輸入流InputStream對象的方法read讀取服務器回寫的數據
        while ((len = is.read(bytes))!=-1){
            System.out.println(new String(bytes,0,len));
        }
        //8、釋放資源(FileInputStream,Socket)
        fis.close();
        socket.close();
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章