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

Java Socket 實現跨伺服器文件傳輸:服務端推送、客戶端接收完整方案

     編輯:Java 相關知識

場景

兩台獨立伺服器之間傳輸大文件,無共享存儲,需自建傳輸通道。採用 Socket 流式傳輸,支持斷點顯示進度。

模組劃分

  1. ServerTest — 服務端,監聽端口,主動推送指定文件。
  2. ClientSocket — 通用 Socket 工具類,封裝連接、發送、接收、關閉。
  3. ClientTest — 客戶端,連接服務端,接收文件並保存,顯示進度百分比。

核心代碼

1. 服務端 (ServerTest)

package sterning;

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

public class ServerTest {
    private static final int PORT = 8821;
    private static final String FILE_PATH = "D:\\lib.rar"; // 待發送文件

    public static void main(String[] args) {
        new ServerTest().start();
    }

    public void start() {
        try (ServerSocket ss = new ServerSocket(PORT)) {
            System.out.println("Server 啟動,等待客戶端連接...");

            while (true) {
                File file = new File(FILE_PATH);
                System.out.println("準備發送: " + file.getName() + " (" + file.length() + " bytes)");

                try (Socket s = ss.accept();
                     DataInputStream in = new DataInputStream(new BufferedInputStream(s.getInputStream()));
                     DataInputStream fis = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
                     DataOutputStream out = new DataOutputStream(s.getOutputStream())) {

                    // 讀取客戶端就緒信號(1 byte)
                    in.readByte();

                    // 發送文件名與長度
                    out.writeUTF(file.getName());
                    out.writeLong(file.length());
                    out.flush();

                    // 流式傳輸文件內容
                    byte[] buf = new byte[8192];
                    int read;
                    while ((read = fis.read(buf)) != -1) {
                        out.write(buf, 0, read);
                    }
                    out.flush();
                    System.out.println("文件傳輸完成");
                } catch (IOException e) {
                    System.err.println("單次傳輸異常: " + e.getMessage());
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2. 通用 Socket 工具類 (ClientSocket)

package sterning;

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

public class ClientSocket {
    private final String ip;
    private final int port;
    private Socket socket;
    private DataOutputStream out;
    private DataInputStream in;

    public ClientSocket(String ip, int port) {
        this.ip = ip;
        this.port = port;
    }

    public void connect() throws IOException {
        socket = new Socket(ip, port);
        out = new DataOutputStream(socket.getOutputStream());
        in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
        System.out.println("連接服務器成功");
    }

    public void sendReadySignal() throws IOException {
        out.writeByte(0x01); // 約定就緒信號
        out.flush();
    }

    public DataInputStream getInputStream() {
        return in;
    }

    public void close() {
        try { if (out != null) out.close(); } catch (IOException ignored) {}
        try { if (in != null) in.close(); } catch (IOException ignored) {}
        try { if (socket != null) socket.close(); } catch (IOException ignored) {}
    }
}

3. 客戶端 (ClientTest)

package sterning;

import java.io.*;

public class ClientTest {
    private static final String SERVER_IP = "localhost";
    private static final int PORT = 8821;
    private static final String SAVE_DIR = "E:\\";

    public static void main(String[] args) {
        new ClientTest().receive();
    }

    public void receive() {
        ClientSocket cs = new ClientSocket(SERVER_IP, PORT);
        try {
            cs.connect();
            cs.sendReadySignal();

            DataInputStream in = cs.getInputStream();
            String fileName = in.readUTF();
            long fileLen = in.readLong();

            File outFile = new File(SAVE_DIR + fileName);
            try (DataOutputStream fos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(outFile)))) {
                byte[] buf = new byte[8192];
                long received = 0;
                int read;
                while ((read = in.read(buf)) != -1) {
                    fos.write(buf, 0, read);
                    received += read;
                    System.out.printf("接收進度: %d%% (%d/%d bytes)%n",
                            received * 100 / fileLen, received, fileLen);
                }
                System.out.println("文件接收完成,保存至: " + outFile.getAbsolutePath());
            }
        } catch (IOException e) {
            System.err.println("接收失敗: " + e.getMessage());
        } finally {
            cs.close();
        }
    }
}

傳輸協議說明

  1. 客戶端連接後發送 1 byte 就緒信號(0x01)。
  2. 服務端發送:UTF-8 文件名 + long 文件長度 + 文件二進制內容。
  3. 雙方均使用 8KB 緩衝區,流式讀寫,內存佔用恆定。

生產環境增強建議

  • 斷點續傳:客戶端先發送已接收字節數,服務端 RandomAccessFile.seek() 續傳。
  • 校驗完整性:傳輸前計算 MD5/SHA256,傳輸後驗證。
  • 壓縮/加密:在流上層包裝 GZIPOutputStream / CipherOutputStream。
  • 多線程並行:大文件分片並發傳輸(需協議支持分片索引)。
  • 優雅關閉:雙向關閉握手,避免數據截斷。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved