首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java TCP 多線程圖片並發上傳實現:Server/Client 完整代碼

     編輯:Java 相關知識

場景說明

客戶端並發上傳圖片文件,服務端以多線程接收並以「客戶端IP_時間戳.jpg」命名保存。圖片屬二進位資料,**必須使用位元組流**(InputStream/OutputStream),不可用字元流。

服務端代碼

import java.io.*;
import java.net.*;

class UploadTask implements Runnable {
    private final Socket socket;

    public UploadTask(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try (InputStream in = socket.getInputStream();
             OutputStream out = socket.getOutputStream()) {

            String ip = socket.getInetAddress().getHostAddress();
            long timestamp = System.currentTimeMillis();
            File outputFile = new File("E:/" + ip + "_" + timestamp + ".jpg");

            try (FileOutputStream fos = new FileOutputStream(outputFile)) {
                byte[] buffer = new byte[1024];
                int len;
                while ((len = in.read(buffer)) != -1) {
                    fos.write(buffer, 0, len);
                }
                fos.flush();
            }

            // 回應客戶端
            out.write("上傳完成...".getBytes());
            out.flush();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try { socket.close(); } catch (IOException ignored) {}
        }
    }
}

public class TCPServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8090);
        System.out.println("服務端啟動,監聽 8090...");

        while (true) {
            Socket client = serverSocket.accept();
            System.out.println("新連接:" + client.getInetAddress());
            new Thread(new UploadTask(client)).start();
        }
    }
}

客戶端代碼

import java.io.*;
import java.net.*;

public class TCPClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 8090);
        System.out.println("已連接服務端");

        try (OutputStream out = socket.getOutputStream();
             FileInputStream fis = new FileInputStream("1.jpg")) {

            byte[] buffer = new byte[1024];
            int len;
            while ((len = fis.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            out.flush();

            // 關鍵:告知服務端發送結束(發送 FIN 包)
            socket.shutdownOutput();

            // 接收回應
            try (InputStream in = socket.getInputStream()) {
                byte[] resp = new byte[1024];
                int rlen = in.read(resp);
                System.out.println("服務端回應:" + new String(resp, 0, rlen));
            }
        } finally {
            socket.close();
        }
    }
}

關鍵技術點解析

點說明
位元組流FileInputStream/FileOutputStream、Socket.getInputStream()/getOutputStream(),不做編碼轉換
shutdownOutput()發送 TCP FIN,讓服務端 read() 返回 -1,否則服務端會永遠阻塞等待數據
多線程隔離每連接一線程,互不干擾,利用多核 CPU
檔案命名IP + 時間戳確保唯一,避免覆蓋
緩衝區大小1024/4096/8192 皆可,過大佔記憶體,過小增加系統調用

進階改進方向

  1. 線程池:替換 new Thread() 為 ExecutorService,控制併發數、復用線程。
  2. 斷點續傳:協議增加文件大小、已傳位移、MD5 校驗。
  3. NIO/Netty:高併發場景下替換 BIO,單線程處理數萬連接。
  4. 安全性:加入 Token 驗證、文件類型檢測(Magic Number)、大小限制。
  5. 進度回調:客戶端顯示上傳進度條。

總結

TCP 文件上傳核心在於:位元組流 + shutdownOutput() 邊界標記 + 多線程並發。上述代碼為教學級最小實現,生產環境請加入線程池、協議幀、異常重試、安全驗證等企業級特性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved