摘要:該文在分析了實現局域網文件共享的關鍵技術要求的基礎上,給出了一個點對點局域網文件共享系統的設計與實現過程,實際測試表明,該系統能夠滿足局域網環境下一般性的文件共享要求,具有一定的實用價值。
關鍵詞:文件共享;點對點;節點發現
中圖分類號:TP393文獻標識碼:A文章編號:1009-3044(2011)04-0782-03
Design and Implementation of a Point-to-Point LAN-Based File Sharing System
CHEN Li
(Tianhe Branch, Guangzhou Radio TV University, Guangzhou 510665, China)
Abstract: Based on the discussion of key technologies for file sharing in LAN, this paper presents the design and implementation of a point-to-point LAN-based file sharing system. The test shows that the system is practical and can satisfy the demand of common file sharing in LAN.
Key words: file sharing; point-to-point; node discovering
隨著計算機與網絡技術的發展,目前大多數企事業單位都組建了自己的局域網,除了在互聯網上進行文件的上傳與下載之外,在局域網內用戶之間的文件互傳與共享功能也是工作的需要。目前大多數用戶使用Windows XP系統,主要利用Windows文件共享功能來完成局域網計算機之間的文件共享,但在實際使用中,往往由于Windows網絡配置等原因,出現網上鄰居訪問速度緩慢,以致找不到對方計算機或者即使找到對方機器,卻始終無法訪問對方共享資源等情況,這給操作帶來不便。為此,開發局域網內點對點文件共享系統將具有實際的應用價值。本文分析了局域網文件共享的關鍵技術要求,在此基礎上,給出了一個點到點局域網文件共享系統的設計過程,并利用Delphi7實現了該系統。
1 關鍵技術要求
目前廣泛使用TCP或UDP協議來實現數據傳輸。TCP是一種面向連接的、可靠的、基于字節流的傳輸層(Transport layer)通信協議,TCP需要經過三次握手才能建立一個數據傳輸連接,它通過相應的差錯控制機制來保證數據的可靠傳輸,但傳輸效率相對較低,對系統資源的要求也比較高;另一種傳輸層的通信協議是UDP,它是不可靠的和無連接的,能夠提供面向事務的簡單而快速的數據傳送服務。對等文件共享節點之間的數據通信主要包括節點間應用協議數據交互(包括節點的控制和狀態信息),以及節點間共享文件的數據傳輸。對于應用協議數據交互,考慮節點間的狀態廣播要求(TCP協議不具有廣播特性)和目前局域網的高速特性,采用UDP協議來完成應用層協議的交互能夠滿足設計上的要求,同時,UDP協議快速高效,也能夠滿足高速局域網環境下的大數據量文件傳輸要求。UDP是一種不可靠的傳輸協議,發送方無法知道接收方是否收到數據包,在網絡狀況不好的情況下,將導致數據丟包的問題。為此,本系統采用以下的設計思路:
1)選擇合適的應用層UDP包大小。UDP報文正文的最大長度是2^16 - 1=65535字節,而以太網鏈路層的最大傳輸單元MTU是1500個字節,一旦報文超過1500字節,將導致鏈路層對報文進行分片。定義合適大小的UDP包,能減少鏈路層對包分片的數量,從而保證報文傳輸的速度和質量。經測試,在局域網內,UDP數據包大小定4096個字節較為合適。
2)采用應答和重傳機制來確保共享文件數據包的可靠傳輸。接收方設置一定的接收緩沖區(大小通常是文件塊大小的整數倍,視不同的網絡狀況進行調整),連續接收發送方發來的文件分塊數據包,若收到第N個包出錯,則指示發送方重新從第N個包開始發送,確保傳送文件的每一個分塊都能傳送到目的地。
2 系統設計與實現
本文完成了系統對等節點間關鍵的節點發現、文件共享列表傳輸與同步和文件傳輸模塊的設計,并給出主要Delphi代碼說明。
2.1 協議數據結構
定義節點間文件傳輸的協議數據結構如下:
1)文件傳輸數據分組類型:TFileTransPacketType = (FTPT_WantFileInfo{請求文件信息},FTPT_WantFileBlock{請求或重傳文件塊}, FTPT_FileTransOK{文件傳輸完畢}, FTPT_FileTransCancel{用戶取消文件傳輸});
2)共享文件元信息:TFileInfo = record//文件信息
FileName: Array [0..255] of Char;//文件名
FileSize: Integer;//文件的大小
CurBlockNo: Integer;//當前文件塊序號
TotalBlocks: Integer;//文件的總塊數
end;
3)文件塊結構:TFileBlock = record
BlockData: Array [0..4095] of Byte;//存放塊數據
BlockSize: Integer;//塊大小
end;
4)文件傳輸請求分組:TFileTransReqPacket = record
ReqPT: TFileTransPacketType;//請求分組類型
FileInfo: TFileInfo;//請求文件的元信息
end;
5)文件傳輸響應分組:TFileTransResPacket = record
FileInfo: TFileInfo;//當前傳輸文件的元信息
FileBlock: TFileBlock;文件塊
end;
2.2 對等節點發現
局域網計算機(對等節點)在通信之前需要按照一定的查找機制發現對方。為此,在系統中需要維護一個局域網范圍的對等共享節點列表,列表的每一個表項記錄其他對等節點的信息。系統使用一個TListView組件(PeerNodesList)來維護本網的節點列表信息,包含計算機名、IP地址、描述、共享服務狀態。節點發現模塊的基本實現過程如下:
1)定時(采用800ms的時鐘定時)向本網段(如192.168.1.255)的特定端口(對等節點的服務偵聽端口,如9999)廣播本機通告分組(包含計算機名、IP地址、描述、共享狀態)。系統采用TidUDPClient組件(UDPClient)來發送數據:
UDPClient.Send('PEER_INFO|'+ComputerName+'|'+IP+'|'+Info+'|'+'1');//Info是本節點描述,1表示本機可為其他節點提供文件共享服務,0表示當前不提供文件共享服務
2)偵聽其他對等節點的通告分組,接收后更新PeerNodesList對等節點列表。系統利用TidUDPServer組件(UDPServer,設置服務偵聽端口UDPServer. DefaultPort:=9999)來接收數據,在UDPServer的OnUDPRead事件處理程序里接收其他節點的通告分組。
3)為PeerNodesList列表里的每一個對等節點設置一個超時時鐘,若時間超過2400ms沒有收到該節點的狀態通告分組,則將其文件共享列表和節點信息刪除。
2.3 共享文件列表的傳輸與同步
系統使用TTreeView組件來維護本地文件共享列表(LocalSharedView)和遠程節點的文件共享列表(RemoteSharedView)。對于本地文件共享列表,實現對允許共享的本地文件或目錄的添加、刪除和重命名共享名的操作,同時可設置每個目錄或文件的訪問權限(文件下載、目錄瀏覽權限,目錄下的所有文件可繼承目錄的操作權限);對于映射到遠端節點的遠程文件共享列表,可從列表中對遠程共享文件或目錄進行刪除與刷新,同時能夠下載指定的遠程共享文件。基本實現過程如下:
1)查看本地節點的共享文件:將LocalSharedView的內容更新為本地共享文件列表(若已經設定);或用戶添加本地文件或目錄為可共享資源。
2)查看遠程節點的共享文件:若該節點當前處于非共享狀態,則從本地配置文件中讀取該節點以前保存的共享文件列表,刷新RemoteSharedView的內容,設定只允許瀏覽權限(只能查看但不能下載),并提示用戶該節點當前不能提供文件共享服務;否則,向遠程目標節點發出獲取文件共享列表請求分組:UDPClient.Send('WANT_LIST');
3)本地節點通過UDPServer接收來自目標節點的文件共享列表(分組類型是’FILE_LIST’),取出其中的文件共享內容,更新到RemoteSharedView視圖,同時設置每個目錄或文件的訪問權限。
4)共享文件列表的同步更新:采用Just-in-time的即時更新策略,即用戶更新本地共享文件列表的內容(如用戶添加、刪除或重命名共享名表項)后,系統將廣播更新后的文件共享列表:UDPClient.Send('FILE_LIST|'+SharedFileList);//SharedFileList包括所有共享的目錄或文件名及其關聯的權限標記,以’|’分隔。
其他對等節點接收后,將該節點的文件共享列表保存到本地配置文件,若該節點當前恰好是遠程共享文件視圖中顯示的內容,則同時更新RemoteSharedView的內容。
2.4 文件數據傳輸
節點間共享文件數據傳輸的實現步驟如下:
1)本地機(客戶端)向遠程機(服務端)請求欲下載文件的元信息:
FileTransReqPacket : TFileTransReqPacket;
FileTransReqPacket.ReqPT := FTPT_WantFileInfo;//請求欲下載文件的文件元信息
FileTransReqPacket.FileInfo.FileName := ‘欲下載文件名’;
UDPClient.SendBuffer(PeerIP, PeerPort, FileTransReqPacket, SizeOf(FileTransReqPacket));
2)服務端通過UDPServer組件接收客戶的文件元信息請求分組:若請求下載的文件存在,則按每塊為4096字節的長度計算文件的總塊數,同時返回文件大小、總塊數以及傳輸文件的第一塊數據給客戶端:
FileTransResPacket : TFileTransResPacket;
FileTransResPacket.FileInfo.FileName := ‘客戶請求下載的文件名’;
FileTransResPacket.FileInfo.FileSize := xxxxxx;//實際文件大小,以字節為單位
FileTransResPacket.FileInfo.TotalBlocks := xxx;//文件的總塊數
FileTransResPacket.FileInfo.CurBlockNo := 1;//同時將第一塊發給客戶端
設置第一塊數據與塊大小 FileTransResPacket.FileBlock.BlockData和BlockSize,然后發送文件塊響應分組FileTransResPacket。
3)客戶端接收服務端返回的下載文件元信息,初始化本地文件下載環境(設置文件大小、總塊數、創建一個新的文件保存文件第一塊數據)。發起請求文件塊傳輸:
with FileTransResPacket do
if (FileBlock.BlockSize = FileInfo.FileSize) then //判斷文件是否傳輸完畢
begin FileTransReqPacket.ReqPT := FTPT_FileTransOK;{文件接收完畢}…end
else begin
FileTransReqPacket.ReqPT := FTPT_WantFileBlock; //希望對方發送文件塊
FileTransReqPacket.FileInfo.CurBlockNo := 2;//希望對方從第二個文件塊開始發送
end;
UDPClient.SendBuffer(PeerIP, PeerPort, FileTransReqPacket, SizeOf(FileTransReqPacket));
4)服務端發送或重傳文件塊的過程:
case FileTransReqPacket.ReqPT of
FTPT_WantFileInfo: //客戶請求文件元信息,處理過程見(2)
FTPT_FileTransOK: //客戶指示文件成功接收完畢,結束當前傳輸,關閉當前文件。
FTPT_FileTransCancel: //用戶中止當前傳輸,釋放發送緩沖區,關閉當前文件。
FTPT_WantFileBlock: begin
//客戶指示從第FileTransReqPacket.FileInfo.CurBlockNo塊開始發送,一旦收到該指示,服務端將停止當前文件塊發送(若已經開始發生,當客戶要求重傳的情況),并從第CurBlockNo塊開始連續發送后續文件塊:
i:= FileTransReqPacket.FileInfo.CurBlockNo;
with FileTransResPacket.FileInfo,FileTransResPacket.FileBlock do
while Not bUserCancel and (i<= FileTransReqPacket.FileInfo.TotalBlocks) do begin
DLFile.Seek((i-1)*SizeOf(BlockData),soBeginning); //定位當前文件塊在下載文件DLFile中的起始位置,讀取文件塊并得到文件塊的大小:
BlockSize := DLFile.Read(BlockData, SizeOf(BlockData));
CurBlockNo := i;//將當前塊的序號返回給客戶
//略去發送文件塊響應分組:FileTransResPacket
end;
end;
end;
5)客戶端連續接收文件塊到緩沖區,若當前塊號失序,則要求對方從該塊開始重傳,若緩沖區滿,則將全部緩沖數據寫到本地文件:
FileRecvBlockCache: Array [0..9] of TFileBlock;//文件塊接收緩沖區
wantBlockNo := FileTransReqPacket.FileInfo.CurBlockNo;//期望的下一個文件塊號
cacheCount := 0; //緩沖區中正確接收的文件塊計數
startCacheIndex := wantBlockNo mod 10;//起始緩沖區數組下標
while Not bUserStop and (wantBlockNo<= FileTransReqPacket.FileInfo.TotalBlocks) do
begin
UDPClient.ReceiveBuffer(FileTransResPacket, SizeOf(FileTransResPacket);
If wantBlockNo= FileTransResPacket.FileInfo.CurBlockNo then begin//序號正確
Move(FileTransResPacket.FileBlock,FileRecvBlockCache[wantBlockNo mod 10],
sizeOf(FileTransResPacket.FileBlock));//將接收的文件塊拷貝到緩沖區
Inc(cacheCount); Inc(wantBlockNo);
If cacheCount=High(FileRecvBlockCache) then begin
//緩沖數據滿,將startCacheIndex開始的cacheCount個文件塊全部寫到本地文件
cacheCount:=0; startCacheIndex:= wantBlockNo mod 10;
end;
end else begin //返回的文件塊失序,要求對方重傳該塊
FileTransReqPacket.ReqPT := FTPT_WantFileBlock; //希望對方重傳文件塊
FileTransReqPacket.FileInfo.CurBlockNo := wantBlockNo;
UDPClient.SendBuffer(PeerIP,PeerPort,FileTransReqPacket, SizeOf(FileTransReqPacket));
end;
end;
if Not bUserStop then //正常接收完畢,將緩沖區中余下cacheCount塊文件塊寫到文件
else //用戶中止傳輸,刪除接收不完整的文件數據
3 結束語
本文分析了局域網環境下點對點文件共享系統的關鍵技術要求,沿用簡單實用的設計思路,利用Delphi7開發了一個基于UDP的點對點局域網文件共享系統。該系統實現了對等節點間的單個文件或整個目錄(包含多個文件)的文件共享功能。系統測試表明,該系統具有較好的文件傳輸性能,界面友好,能滿足一般性的文件互傳要求,有一定的實用價值。但在實際使用中,我們也發現在網絡狀況不理想的情況下,也存在大數據量文件傳輸中斷或緩慢的現象,這些在新版本中需要設計更健壯的傳輸機制,如采用改進重傳機制來保證數據的可靠傳輸,另外,可考慮提供斷點續傳機制和實現點對多點的文件傳輸,使系統更加實用、高效。
參考文獻:
[1] 張建忠,徐敬東.計算機網絡技術與應用[M].北京:機械工業出版社,2010.
[2] 徐昌彪,鮮永菊.計算機網絡中的擁塞控制與流量控制[M].北京:人民郵電出版社,2007.
[3] 張仿彥.Delphi接口技術開發實例解析[M].北京:機械工業出版社,2007.
[4] 賽奎春,宋坤,趙智勇,等.Delphi信息系統開發實例精選[M].北京:機械工業出版社,2005.