首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> .NET 實例教學

解決 FTP「基礎連線已關閉:伺服器提交了協定衝突」C# 完整排查指南

     編輯:.NET 實例教學

FtpWebRequest 協定衝突錯誤根因與三種解決方案

使用 `FtpWebRequest.GetResponse()` 連接特定 FTP 伺服器時拋出「The underlying connection was closed: The server committed a protocol violation」,但 FileZilla、WinSCP 等用戶端正常。經排查,主因在於 **伺服器回應不符合 RFC 959/2428 標準**(如多行回應格式錯誤、狀態碼異常),導致 .NET 內建 FTP 解析器拋出例外。

重現代碼片段

var req = (FtpWebRequest)WebRequest.Create($"ftp://{host}:{port}/");
req.Credentials = new NetworkCredential(user, pass);
req.Method = WebRequestMethods.Ftp.ListDirectory;
req.UseBinary = true;
req.UsePassive = true; // 關鍵嘗試
using (var resp = (FtpWebResponse)req.GetResponse()) // 這裡拋出 ProtocolViolationException
using (var reader = new StreamReader(resp.GetResponseStream()))
    Console.WriteLine(reader.ReadToEnd());

方案一:啟用 `useUnsafeHeaderParsing`(最快生效)

.NET 配置選項允許寬鬆解析不標準 HTTP/FTP 標頭。在 `app.config` / `web.config`:

<system.net>
  <settings>
    <httpWebRequest useUnsafeHeaderParsing="true" />
  </settings>
</system.net>

或運行時代碼(需反射,因屬性 `internal`):

var settings = typeof(System.Net.Configuration.SettingsSection).GetSection("system.net/settings");
var prop = settings.GetType().GetProperty("HttpWebRequest", BindingFlags.NonPublic | BindingFlags.Instance);
var httpSettings = prop.GetValue(settings);
var unsafeProp = httpSettings.GetType().GetProperty("UseUnsafeHeaderParsing", BindingFlags.NonPublic | BindingFlags.Instance);
unsafeProp.SetValue(httpSettings, true);

方案二:改用 `FtpWebRequest` 低階 Socket 或第三方庫

  • FluentFTP(推薦):`NuGet Install FluentFTP`,支援非標準伺服器、TLS/SSL、非同步、大檔案斷點續傳。
    using var conn = new FtpClient(host, user, pass);
    conn.Connect();
    foreach (var f in conn.GetListing()) Console.WriteLine(f.Name);
  • Rebex FTP/SSL:商業庫,相容性極佳。
  • Raw Socket 實作 FTP 指令:完全控制,但需自行處理協定細節(PASV/EPSV、多行回應、編碼)。

方案三:伺服器端修正(根治)

若可控制 FTP 伺服器(如 vsftpd、ProFTPD、FileZilla Server、IIS FTP):

  • 升級至最新版,修正已知協定合規性 Bug。
  • 檢查 `ftpd.log` 確認回應格式:每行必須以 `` 或 `-` 開頭,結尾 `\r\n`。
  • 關閉不必要的擴展指令(如 `MLST`、`UTF8`)測試是否為特定指令觸發。

診斷技巧

  1. 啟用 `System.Net` 追蹤輸出原始交互:
    <system.diagnostics>
      <trace autoflush="true" />
      <sources>
        <source name="System.Net" maxdatasize="1024">
          <listeners><add name="netlog" /></listeners>
        </source>
      </sources>
      <sharedListeners>
        <add name="netlog" type="System.Diagnostics.TextWriterTraceListener" initializeData="ftp_trace.log" />
      </sharedListeners>
      <switches>
        <add name="System.Net" value="Verbose" />
      </switches>
    </system.diagnostics>
  2. 用 `telnet host 21` 手動輸入 `USER`、`PASS`、`PASV`、`LIST` 觀察原始回應。
  3. Wireshark 抓包分析 TCP 流,對照 RFC 959 找出不合規行。
  4. 最佳實務清單

    1. 優先升級 .NET Framework / .NET Core 至最新版(內建 FTP 解析器持續改進)。
    2. 新專案**直接採用 FluentFTP**,避開 `FtpWebRequest` 歷史包袱。
    3. 舊專案若無法換庫,加上 `useUnsafeHeaderParsing=true` 並加強記錄監控。
    4. 納入 CI/CD 測試:自動對目標 FTP 伺服器執行 `ListDirectory`、`Upload`、`Download` 驗證相容性。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved