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

FTP上传报错:无法写入传输连接,求原因分析

问题描述

我开发了一个将文件上传至路由器FTP服务器(挂载U盘)的应用,文件数量不多,单文件最大20MB,也包含小型TXT文件。最初采用逐字节写入的FTP上传方法,代码如下:

private void UploadFileFtp(string filePathTemp, Uri filePathFtp, IProgress<float> progressOneFile)
{
    FtpWebRequest ftpWeb = FtpWebRequest.Create(filePathFtp) as FtpWebRequest;
    ftpWeb.Method = WebRequestMethods.Ftp.UploadFile;
    ftpWeb.UseBinary = true;
    using Stream streamRequest = ftpWeb.GetRequestStream();
    using FileStream reader = new FileStream(filePathTemp, FileMode.Open);

    var lenghtBytes = ftpWeb.ContentLength = reader.Length;
    int @byte = reader.ReadByte();
    long countBytes = 1;
    int oldPrecent = 0;
    while (@byte != -1)
    {
        streamRequest.WriteByte((byte)@byte);
        @byte = reader.ReadByte();

        int precent = (int)(countBytes++ * 100 / lenghtBytes);
        if (precent != oldPrecent)
        {
            oldPrecent = precent;
            progressOneFile.Report(precent / 100f);
        }

    }
    streamRequest.Flush();
    streamRequest.Close();
    using FtpWebResponse response = ftpWeb.GetResponse() as FtpWebResponse;
    if (!response.StatusDescription.Contains("226") && response.StatusCode != FtpStatusCode.ClosingData)
    {
        throw new Exception("Error in fileUnploading" + filePathTemp);
    }
}

在本地及外部网络的笔记本测试均正常,但在朋友的DIR-825路由器上触发错误Unable to write data to the transport connection,且路由器会死机需重启;我的路由器上文件写入流会挂起。排除某一文件后,错误会转移到其他文件。

尝试关闭路由器防火墙、调整KeepAlive、UsePassive等属性均无效。随后重构为缓冲区批量写入的上传方法,代码如下:

private void UploadFileFtp(string filePathTemp, Uri filePathFtp, IProgress<float> progressOneFile)
{
    FtpWebRequest ftpWeb = FtpWebRequest.Create(filePathFtp) as FtpWebRequest;
    ftpWeb.Method = WebRequestMethods.Ftp.UploadFile;
    ftpWeb.UseBinary = true;
    ftpWeb.ConnectionGroupName = "uploadftp";
    using FileStream reader = new FileStream(filePathTemp, FileMode.Open);
    var lenghtBytes = ftpWeb.ContentLength = reader.Length;

    byte[] buffer = new byte[1024];

    using Stream streamRequest = ftpWeb.GetRequestStream();
    int @byte = reader.Read(buffer, 0, buffer.Length);
    long countIterationWrite = @byte;
    int oldPrecent = 0;
    while (@byte != 0)
    {
        streamRequest.Write(buffer, 0, buffer.Length);
        @byte = reader.Read(buffer, 0, buffer.Length);

        int precent = (int)((countIterationWrite+= @byte) * 100 / lenghtBytes);
        if (precent != oldPrecent)
        {
            oldPrecent = precent;
            progressOneFile.Report(precent/100f);
        }

    }
    streamRequest.Flush();
    streamRequest.Close();
    using FtpWebResponse response = ftpWeb.GetResponse() as FtpWebResponse;
    if (!response.StatusDescription.Contains("226") && response.StatusCode != FtpStatusCode.ClosingData)
    {
        throw new Exception("Ошибка при загрузке файла " + filePathTemp);
    }
}

调整后可正常上传,但将缓冲区大小设为1字节时错误复现。请问这一现象的原因是什么?

问题原因分析
  1. 路由器FTP服务器的资源瓶颈
    路由器属于嵌入式设备,CPU、内存等硬件资源极为有限,其内置的FTP服务器仅针对常规批量数据传输做了优化,无法处理高频小数据包的冲击。逐字节上传时,每发送1字节就会触发一次TCP传输交互,短时间内产生海量数据包和TCP确认(ACK)请求,直接耗尽路由器的CPU和内存,导致连接中断甚至设备死机。

  2. TCP协议的交互开销问题
    TCP是面向连接的可靠协议,每次发送小数据包后都需要等待接收方的ACK确认。逐字节传输会让TCP连接始终处于"发送-等待-确认"的循环,不仅传输效率极低,还会导致网络栈缓冲区被大量待确认的微小数据包占满,最终引发传输连接超时或写入失败的错误。

  3. FtpWebRequest的底层行为特性
    FtpWebRequest的WriteByte方法没有内置缓冲机制,会直接触发底层网络写入操作。当缓冲区设为1字节时,本质和逐字节写入完全一致,同样会产生高频小数据包,触发资源耗尽问题;而使用1024字节这类常规缓冲区时,数据被批量打包发送,大幅减少TCP交互次数,降低路由器的处理压力,从而避免错误。

内容的提问来源于stack exchange,提问作者Евгений Кудик

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 19:47:52