You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现TcpListener分块接收TcpClient发送的大文件?

分块实现C# TCP文件传输

客户端修改代码

替换原一次性加载文件的逻辑,改用分块读取文件流传输,同时新增文件大小元数据传输:

// 分块大小可根据网络情况调整,默认用4KB平衡内存与效率
const int BufferSize = 4096;

string fileName = "目标文件路径";
FileInfo fileInfo = new FileInfo(fileName);

using (FileStream fileStream = fileInfo.OpenRead())
using (NetworkStream networkStream = client.GetStream()) // client为你的TcpClient实例
{
    // 1. 发送文件名长度(4字节int)
    byte[] fileNameBytes = Encoding.UTF8.GetBytes(fileInfo.Name);
    byte[] fileNameLenBytes = BitConverter.GetBytes(fileNameBytes.Length);
    await networkStream.WriteAsync(fileNameLenBytes, 0, fileNameLenBytes.Length);

    // 2. 发送文件名内容
    await networkStream.WriteAsync(fileNameBytes, 0, fileNameBytes.Length);

    // 3. 发送文件总大小(8字节long,支持超大文件)
    byte[] fileSizeBytes = BitConverter.GetBytes(fileStream.Length);
    await networkStream.WriteAsync(fileSizeBytes, 0, fileSizeBytes.Length);

    // 4. 分块发送文件内容
    byte[] buffer = new byte[BufferSize];
    int bytesRead;
    while ((bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
    {
        await networkStream.WriteAsync(buffer, 0, bytesRead);
    }
}

服务器修改代码

改为先解析元数据,再根据文件大小循环接收分块,避免一次性占用大量内存:

const int BufferSize = 4096;
string receivedFilePath = "文件保存目录";

using (NetworkStream networkStream = currentClient.GetStream()) // currentClient为已连接的TcpClient
{
    // 1. 读取文件名长度
    byte[] fileNameLenBuffer = new byte[4];
    await networkStream.ReadAsync(fileNameLenBuffer, 0, fileNameLenBuffer.Length);
    int fileNameLen = BitConverter.ToInt32(fileNameLenBuffer, 0);

    // 2. 读取文件名
    byte[] fileNameBuffer = new byte[fileNameLen];
    await networkStream.ReadAsync(fileNameBuffer, 0, fileNameBuffer.Length);
    string fileName = Encoding.UTF8.GetString(fileNameBuffer);
    string fullSavePath = Path.Combine(receivedFilePath, fileName);

    // 3. 读取文件总大小
    byte[] fileSizeBuffer = new byte[8];
    await networkStream.ReadAsync(fileSizeBuffer, 0, fileSizeBuffer.Length);
    long fileSize = BitConverter.ToInt64(fileSizeBuffer, 0);

    // 4. 分块接收并写入文件
    using (FileStream fileStream = new FileStream(fullSavePath, FileMode.Create, FileAccess.Write))
    {
        byte[] buffer = new byte[BufferSize];
        long totalReceived = 0;
        int bytesRead;

        while (totalReceived < fileSize)
        {
            // 计算本次需接收的字节数(取剩余大小与缓冲区的最小值)
            int receiveSize = (int)Math.Min(BufferSize, fileSize - totalReceived);
            bytesRead = await networkStream.ReadAsync(buffer, 0, receiveSize);
            
            if (bytesRead == 0) break; // 处理连接意外断开的情况

            await fileStream.WriteAsync(buffer, 0, bytesRead);
            totalReceived += bytesRead;
        }
    }
}

关键改进点

  • 分块传输:避免大文件一次性加载到内存,降低内存占用
  • 明确协议:通过「文件名长度→文件名→文件大小」的元数据顺序,让服务器精准解析传输内容
  • 资源安全:所有流对象使用using语句自动释放,避免内存泄漏
  • 可靠接收:通过已接收字节数与文件总大小的对比,确保完整接收所有数据

内容的提问来源于stack exchange,提问作者Fadzii

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 17:12:45