基於FTP協議實現FTP客戶端和服務端程序

摘要

FTP的目標是提高文件的共享性,提供非直接使用遠程計算機,使存儲介質對用戶透明和可靠高效地傳送數據。雖然我們也可以手工使用它,但是它的主要作用是供程序使用的。本文詳細介紹了FTP協議內容及FTP工作原理以及基於FTP協議通過C#實現FTP客戶端和FTP服務端。

1 FTP協議

文件傳輸協議FTP(File Transfer Protocol)是因特網中使用最廣泛的文件傳輸協議。FTP使用交互式的訪問,允許客戶指定文件的類型和格式(如指明是否使用ASCII碼),並允許文件具有存取權限(如訪問文件的用戶必須經過授權,並輸入有效的口令)。

  文件傳輸協議有基於TCP的FTP和基於UDP的簡單文件傳輸協議TFTP,它們都是文件共享協議中的一大類,即複製整個文件,其特點是:若要存取一個文件,就必須先獲得一個本地的文件副本。如果要修改文件,只能對文件的副本進行修改,然後再將修改後的文件傳回到原節點。

2 FTP服務基本工作原理

 FTP屏蔽了各計算機系統的細節,因而適合在異構網絡中任意計算機之間傳送文件。FTP只提供文件傳送的一些基本服務,它使用TCP可靠地運輸服務,FTP主要功能是減小或消除在不同系統下處理文件的不兼容性。

  FTP使用客戶端-服務器模型,一個FTP服務器進程可以爲多個客戶進程提供服務。FTP服務器有兩大部分組成:一個主進程,負責接受新的請求;還有若干從屬進程,負責處理單個請求。主進程工作步驟

  • 打開熟知端口(21),使客戶進程能夠連接上
  • 等待客戶進程發送連接請求
  • 啓動從屬進程處理客戶進程發送的連接請求,從屬進程處理完請求後結束,從屬進程在運行期間可能根據需要可創建其他一些子進程
  • 回到等待狀態,繼續接受其他客戶進程發起的請求,主進程與從屬進程的處理是併發進行的

FTP工作時情況

  FTP控制連接在整個會話期間都保持打開,只用來發送連接/傳送請求。當客戶進程向服務器發送連接請求時,尋找連接服務器進程的熟知端口21,同時還要告訴服務器進程自己的另一個端口號碼,用於建立數據傳送連接。接着,服務器進程用自己傳送數據的熟知端口20與客戶進程所提供的端口號碼建立數據傳送連接,FTP使用了2個不同的端口號,所以數據連接和控制連接不會混亂。

2.1 FTP數據表示

  FTP協議規定了控制協議傳送與存儲的多種選擇,在以下4個方面必須做出一個選擇。

  • 文件類型:ASCII碼文件(默認的)/ 圖像文件類型(二進制的)/ 本地文件類型(用於在具有不同字節大小主機間傳送二進制數據)
  • 格式控制:該選項針對ASCII類型文件適用,非打印(默認選擇,文件中不包含垂直格式信息)/ 遠程登錄格式控制
  • 結構:文件結構(默認選擇,文件被認爲是一個連續的字節流,不存在內部的文件結構)/ 記錄結構(用於文本文件)
  • 傳輸方式:流方式(模式選擇,文件以字節流方式傳輸,對於文件結構,發方在文件尾提示關閉數據連接,對於記錄結構,有專用的兩字節序列碼記錄結束和文件結束)/ 塊方式(文件以一系列塊來傳送,每塊前面有一個或多個首部字節)/ 壓縮方式

2.2 FTP命令和應答

  命令和應答在客戶和服務器的控制連接上以 NVT ASCII碼形式傳送。這就要求在每行結尾都要返回C R、 L F對(也就是每個命令或每個應答)。這些命令都是3或4個字節的大寫ASCII字符,其中一些帶選項參數。從客戶向服務器發送的FTP命令超過30種。下圖是比較常用的幾種命令:

  應答都是ASCII碼形式的3位數字,並跟有報文選項。其原因是軟件系統需要根據數字代碼來決定如何應答,而選項串是面向人工處理的。由於客戶通常都要輸出數字應答和報文串,一個可交互的用戶可以通過閱讀報文串(而不必記憶所有數字回答代碼的含義)來確定應答的含義。

2.3 FTP工作模式

FTP有兩種工作模式,分別是主動模式(PORT)和被動模式(PASV)兩種模式,這兩種模式是按照FTP服務器的“角度”來說的,更通俗一點說就是:在傳輸數據時,如果是服務器主動連接客戶端,那就是主動模式;如果是客戶端主動連接服務器,那就是被動模式。

  1. 主動模式 (PORT)

主動模式下,客戶端隨機打開一個大於 1024 的端口向服務器的命令端口 P,即 21 端口,發起連接,同時開放N +1 端口監聽,並向服務器發出 “port N+1” 命令,由服務器從它自己的數據端口 (20) 主動連接到客戶端指定的數據端口 (N+1)。FTP 的客戶端只是告訴服務器自己的端口號,讓服務器來連接客戶端指定的端口。對於客戶端的防火牆來說,這是從外部到內部的連接,可能會被阻塞。

爲了解決服務器發起到客戶的連接問題,有了另一種 FTP 連接方式,即被動方式。命令連接和數據連接都由客戶端發起,這樣就解決了從服務器到客戶端的數據端口的連接被防火牆過濾的問題。

  1. 被動模式 (PASV)

被動模式下,當開啓一個 FTP 連接時,客戶端打開兩個任意的本地端口 (N > 1024 和 N+1) 。第一個端口連接服務器的 21 端口,提交 PASV 命令。然後,服務器會開啓一個任意的端口 (P > 1024 ),返回如“227 entering passive mode (127,0,0,1,4,18)”。這意味着在服務器上有一個端口被開放。客戶端收到命令取得端口號之後, 會通過 N+1 號端口連接服務器的端口 P,然後在兩個端口之間進行數據傳輸。

3 實現FTP客戶端和服務端程序

FTP客戶端部分代碼,實現上傳文件和下載文件:

        /// <summary>
        /// 文件上傳
        /// </summary>
        /// <param name="fileLocalPath">文件在本地的路徑</param>
        /// <param name="filePathInfo">文件將上傳到服務器的路徑信息</param>
        /// <returns></returns>
        public void UploadFile(string fileLocalPath,string destRelativePath)
        {
            try
            {
                FileInfo fileInfo = new FileInfo(fileLocalPath);
                string uri = GetUri(destRelativePath);
                FtpWebRequest request = CreateFtpWebRequest(uri, WebRequestMethods.Ftp.UploadFile);
                request.ContentLength = fileInfo.Length;
                byte[] buffer = new byte[BufLength];
                FileStream fileStream = fileInfo.OpenRead();
                Stream resquestStream = request.GetRequestStream();
                int contentLength = fileStream.Read(buffer, 0, BufLength);
                while (contentLength != 0)
                {
                    resquestStream.Write(buffer, 0, contentLength);

                    contentLength = fileStream.Read(buffer, 0, BufLength);
                }
                resquestStream.Close();
                fileStream.Close();
                FtpWebResponse response = (FtpWebResponse)request.GetResponse();
                if (response == null)
                {
                    throw new Exception("服務器未響應");
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 下載文件
        /// </summary>
        /// <param name="sourcePath">文件在服務器的路徑信息</param>
        /// <param name="destPath">文件下載到本地的路徑</param>
        /// <returns></returns>
        public void DownloadFile(string sourceRelaticePath,string destAbsolutionPath)
        {
            try
            {
                string uri = GetUri(sourceRelaticePath);
                FtpWebRequest request = CreateFtpWebRequest(uri, WebRequestMethods.Ftp.DownloadFile);
                FtpWebResponse response = (FtpWebResponse)request.GetResponse();
                Stream responseStream = response.GetResponseStream();
                if (response == null)
                {
                    throw new Exception("服務器未響應");
                }
                FileInfo fileInfo = new FileInfo(destAbsolutionPath);
                if (!fileInfo.Directory.Exists)
                {
                    fileInfo.Directory.Create();
                }
                FileStream fileStream = fileInfo.Create();
                int buflength = 8196;
                byte[] buffer = new byte[buflength];
                int bytesRead = 1;
                while (bytesRead != 0)
                {
                    bytesRead = responseStream.Read(buffer, 0, buflength);
                    fileStream.Write(buffer, 0, bytesRead);
                }
                responseStream.Close();
                fileStream.Close();
            }
            catch
            {
                throw;
            }
        }
        private FtpWebRequest CreateFtpWebRequest(string uri, string command)
        {
            FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(uri);
            request.Credentials = netCrediental;
            request.KeepAlive = true;
            request.UseBinary = true;
            request.Method = command;
            return request;
        }

        private string GetUri(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                return serverUri;
            }
            return string.Concat(serverUri, "/", path);
        }

不同系統在系統自帶服務中都提供了對應平臺的FTP服務器程序,用戶可自行啓用。在Window系統下用戶可在啓用或關閉Windows功能中啓用FTP服務器,然後在通過IIS控制檯添加FTP站點啓動FTP服務器。

本項目中FTP服務器採用自行實現的服務器,實現了FTP協議常用的命令。

完整項目CSDN路徑https://download.csdn.net/download/uiuan00/11966603

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章