案例——TCP上傳圖片
- 2019 年 10 月 19 日
- 筆記
TCP上傳圖片
繼續做一個TCP的相關案例,在客戶端上傳一張圖片到服務端,服務端收到圖片後,給客戶端回饋上傳成功資訊。
實現細節:
- 對於一些文件的讀取,若文件偏大,可以始用緩衝區去讀取和寫入,可以提高效率
- 服務端面向的是很多用戶,所以必須要開執行緒來接收
- 如果同一個用戶上傳多張圖片則有可能文件名重複,所以要對文件名做處理,具體在程式碼處有注釋
- 客戶端圖片上傳完成後需要給服務端發送結束資訊,s.shutdownOutput();
就像是寫入了一個終止符一樣
客戶端
需要在上傳結束的時候寫入終止符告訴服務端上傳結束,可以雙方約定一個終止的符號,也可以用shutdownOutput()方法來傳遞結束資訊
import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.Socket; public class UploadPicClient { public static void main(String[] args) throws IOException { System.out.println("上傳圖片客戶端啟動..."); //1、創建socket Socket s = new Socket("127.233.24.3", 10018); //2、讀取源圖片 File picFile = new File("D:\forio\download.jpg"); BufferedInputStream fis = new BufferedInputStream(new FileInputStream(picFile)); //3、目的:socket輸出流,發送到服務端 OutputStream out = s.getOutputStream(); byte[] buf = new byte[1024]; int len = 0; while((len = fis.read(buf)) != -1) { out.write(buf, 0, len); } //告訴服務端 圖片發送完成,不要在等著讀了 s.shutdownOutput(); //讀取上傳成功字樣 BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream())); String info = in.readLine(); System.out.println(info); //關閉 fis.close(); s.close(); } }
服務端
服務端需要多執行緒接收多個客戶的上傳資訊,對於有可能存在的文件名重複,添加(1)(2)(3)…加以區分
import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; public class UploadPicServer { public static void main(String[] args) throws IOException { System.out.println("上傳圖片服務端啟動..."); // 創建ServerSocket ServerSocket ss = new ServerSocket(10018); while (true) { // 獲取客戶端 Socket s = ss.accept(); // 實現多個客戶端並發上傳,伺服器端必須啟動做個執行緒來完成 new Thread(new UploadPic(s)).start(); } } } class UploadPic implements Runnable { private Socket s; public UploadPic(Socket s) { super(); this.s = s; } @Override public void run() { try { String ip = s.getInetAddress().getHostAddress(); System.out.println(ip + "connected..."); // 寫圖片數據到文件的輸出流 File dir = new File("D:\forio\photo"); // 為了避免重名覆蓋,通過給重名文件進行編號 int count = 1; File picFile = new File(dir, ip + "(" + count + ")" + ".jpg"); while (picFile.exists()) { count++; picFile = new File(dir, ip + "(" + count + ")" + ".jpg"); } FileOutputStream fos = new FileOutputStream(picFile); // 讀取客戶端發來的數據 InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = 0; while ((len = in.read(buf)) != -1) { fos.write(buf, 0, len); } // 給客戶端一個回饋資訊 BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); out.write("上傳成功!"); // 寫完需要刷新一下,或者關閉流 // 關閉資源 out.close(); fos.close(); s.close(); } catch (Exception e) { } } }
結果演示