1. 程式人生 > 程式設計 >java模擬客戶端向伺服器上傳檔案

java模擬客戶端向伺服器上傳檔案

本文例項為大家分享了java客戶端向伺服器上傳檔案的具體程式碼,供大家參考,具體內容如下

先來了解一下客戶端與伺服器Tcp通訊的基本步驟:

  • 伺服器端先啟動,然後啟動客戶端向伺服器端傳送資料。
  • 伺服器端收到客戶端傳送的資料,伺服器端會響應應客戶端,向客戶端傳送響應結果。
  • 客戶端讀取伺服器傳送的資料

檔案上傳步驟:

客戶端使用本地位元組輸入流,指定上傳資料的資料來源。

客戶端使用網路位元組輸出流,把讀取的本地檔案上傳到伺服器。

伺服器使用網路位元組輸入流,讀取客戶端上傳的檔案。

伺服器使用本地位元組輸出流,把讀取到的檔案儲存到伺服器硬碟上。

伺服器使用網路位元組輸出流,給客戶端響應一個“上傳成功”。

客戶端使用網路位元組輸入流,讀取伺服器響應的資料。

客戶端的程式碼實現

public class fileClient {
     public static void main(String[] args) throws IOException {
       FileInputStream fis = new FileInputStream("D:\\1.jpg");//建立一個本地的輸入流,用於指定上傳資料的資料來源
       Socket socket = new Socket("127.0.0.1",8888);//建立一個客戶端物件,host是伺服器名稱或Ip地址
       OutputStream os = socket.getOutputStream();//使用socket中的方法,獲取網路位元組輸出流物件
   
       byte[] bytes = new byte[1024];//把本地硬碟的資料通過網路位元組輸出流傳遞給客戶端
       int len = 0;
       while ((len = fis.read(bytes))!=-1){
         os.write(bytes,len);
       }
   
       socket.shutdownOutput();//為了解決阻塞問題
   
       InputStream is = socket.getInputStream();//使用socket中的方法,獲取網路位元組輸入流,用於讀取客戶端的資料
       while((len = is.read(bytes))!=-1){//讀取客戶端的資料進行輸出
         System.out.println(new String(bytes,len));
       }
   
       socket.close();//關閉流
       fis.close();
     }
   }

伺服器端程式碼實現

public class fileServer {
  public static void main(String[] args) throws IOException {
    ServerSocket serverSocket = new ServerSocket(8888);//建立伺服器端物件



    //while(true){//讓伺服器一直處於執行狀態,保證客戶端可以隨時向伺服器上傳檔案
      new Thread(new Runnable() {//為了提高檔案上傳效率,來一個客戶端開一個執行緒
        @Override
        public void run() {
          try{
            Socket socket = serverSocket.accept();//使用accept方法接收客戶端的資料
            InputStream is = socket.getInputStream();//建立網路位元組輸入流

            File file = new File("D:\\upload");//判斷伺服器硬碟中的資料夾是否存在,此資料夾用於儲存客戶端上傳的內容
            if (!file.exists()){//判斷伺服器端的資料夾是否存在
              file.mkdirs();
            }

            String fileName = "\\picture"+System.currentTimeMillis()+new Random().nextInt(99999)+".jpg";//自己隨機生成檔名,防止重複

            FileOutputStream fos = new FileOutputStream(file+fileName);//

            int len;
            byte[] bytes = new byte[1024];
            while((len = is.read(bytes))!= -1 ){//將客戶端的資料寫入伺服器硬碟中
              fos.write(bytes,len);
            }

            OutputStream os = socket.getOutputStream();//向客戶端迴應
            os.write("上傳成功".getBytes());

            socket.close();
            fos.close();
          }catch (IOException e){//在這裡只能使用try catch解決異常,因為run方法不支援丟擲異常
            System.out.println(e);
          }

        }
      }).start();
    //}

  }
}

注:在開啟多執行緒的時候,因為run方法的父類並不支援throws解決異常,所以run也不支援,只能使用try…catch解決異常

解釋一下為什麼在上傳資料的時候客戶端和伺服器會出現阻塞問題以及解決阻塞的方法

為什麼會出現阻塞?

出現阻塞的根本問題是,客戶端從本地硬碟讀取檔案給伺服器的時候,因為用的是while迴圈,所以檔案的結束符-1並沒有被讀取到伺服器,這時上傳到伺服器的檔案就沒有結束符,伺服器把讀取到的檔案儲存到伺服器硬碟上時就會一直執行while迴圈,導致阻塞。另外還有一個阻塞時伺服器向客戶端響應檔案時候的阻塞。

解決阻塞問題的方法?

阻塞問題的根本原因就是因為在讀取的時候沒有結束符,用 socket.shutdownOutput() 給上傳的檔案一箇中止序列。

API對 shutdownOutput() 的解釋:對於 TCP 套接字,任何以前寫入的資料都將被髮送,並且後跟 TCP的正常連線終止序列。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。