劉睿,任曉慧,于波
(聊城大學(xué)計算機(jī)學(xué)院,聊城252000)
當(dāng)代社會步入一個高速發(fā)展的時代,科技發(fā)達(dá)、信息流通,人們之間的交流越來越密切,信息資源也成為國家發(fā)展、社會進(jìn)步的重要戰(zhàn)略資源,信息的傳播與分享成為創(chuàng)造效率的必要條件。文件作為互聯(lián)網(wǎng)信息傳輸常用載體之一,其分發(fā)傳輸在內(nèi)容分發(fā)網(wǎng)絡(luò)、P2P 網(wǎng)絡(luò)等方面都有比較成熟的研究和應(yīng)用成果。而在日常教學(xué)及工作中,經(jīng)常需要將規(guī)模小的信息以文件的方式快速分發(fā)出去,距離近(如位于同一局域網(wǎng)中的辦公室之間或者教室、機(jī)房內(nèi)),如何提高工作效率以及辦公質(zhì)量是本文所設(shè)計文件共享方式的初衷。目前也有許多學(xué)者進(jìn)行過相關(guān)的研究,文獻(xiàn)[1]中研究實現(xiàn)了一種基于Python 語言的分布式文件共享系統(tǒng),本文同樣采用Python 語言編程,實現(xiàn)了分布式文件共享的功能,并在其基礎(chǔ)上進(jìn)行了優(yōu)化設(shè)計:通過寫入數(shù)據(jù)庫表的形式,實現(xiàn)對分享條目的動態(tài)修改和對無效信息的及時清除,減少數(shù)據(jù)冗余;通過利用系統(tǒng)的體系監(jiān)控機(jī)制,實現(xiàn)針對常見系統(tǒng)平臺(包括Windows 及Linux等)的動態(tài)監(jiān)控。最終可實現(xiàn):加入網(wǎng)絡(luò)環(huán)境中的每一個成員,都成為信息的發(fā)布者和分享者,快速分發(fā),提高工作效率。
在日常的辦公及學(xué)習(xí)時,常見的文件共享方式一般有以下幾種[1]:通過現(xiàn)代商業(yè)辦公體系和一些即時通訊工具進(jìn)行傳輸;建立FTP 協(xié)議的服務(wù)器進(jìn)行文件共享;通過郵箱發(fā)送郵件的形式;使用存儲設(shè)備拷貝共享等。這些傳輸方式類型多樣,各有利弊,但共同點是都借用了第三方工具,獲取效率有所影響。本文設(shè)計實現(xiàn)的分布式文件共享方式特點為:實時查看,實時下載,方便快捷。該共享方式將網(wǎng)絡(luò)中內(nèi)部成員需要傳遞的文件信息加入到共享系統(tǒng)中來,要想獲得這些信息,其他客戶端只需以網(wǎng)頁的形式使用關(guān)鍵字搜索即可快速實現(xiàn)。
Peer-to-Peer(簡稱P2P,即對等方式技術(shù))[2-3],是小型局域網(wǎng)常用的組網(wǎng)方式。其可以定義為:網(wǎng)絡(luò)的參與者共享他們所擁有的一部分硬件資源,這些共享資源通過網(wǎng)絡(luò)提供服務(wù)和內(nèi)容,能被其他對等節(jié)點(Peer)直接訪問而無需經(jīng)過中間實體。在此網(wǎng)絡(luò)中的參與者既是資源、服務(wù)和內(nèi)容的提供者,又是資源、服務(wù)和內(nèi)容的獲取者。
本文所設(shè)計的P2P 文件共享方式屬于集中式P2P網(wǎng)絡(luò)共享方式[2]。Peer 同時具有Client 和Server 的特點,可以直接通信和文件傳輸[4]。
選擇使用Python 語言進(jìn)行服務(wù)器端、客戶端程序設(shè)計,是因為Python 語言是一種語法簡潔優(yōu)美、功能強(qiáng)大、應(yīng)用領(lǐng)域廣泛,具有強(qiáng)大完備的第三方庫的一種可移植、可擴(kuò)展、可嵌入的解釋型編程語言。Python 語言誕生于1990 年,由Guido van Rossum 設(shè)計并領(lǐng)導(dǎo)開發(fā),目前是一種被廣泛使用的高級通用腳本編程語言[5-6]。它的特點是:語法簡潔、與平臺無關(guān),有優(yōu)異的可擴(kuò)展性;Python 語言提供了豐富的內(nèi)置類庫和函數(shù)庫,可以大量利用已有的內(nèi)置或第三方代碼,能夠輕量級地完成各種任務(wù),用于編寫各領(lǐng)域的應(yīng)用程序。Python 語言相對簡潔、開發(fā)效率高、易于維護(hù),目前已經(jīng)成為眾多科研領(lǐng)域使用的科學(xué)計算工具[7],具有廣闊的應(yīng)用空間。使用Python 語言進(jìn)行設(shè)計,可充分享受其代碼簡潔,語義容易理解的優(yōu)勢,缺點在于運行速度稍慢,代碼不能加密等,對于實用的小程序來講,此點可忽略。
本文系統(tǒng)的實現(xiàn)方式如下:在同一局域網(wǎng)或可以互相訪問的虛擬局域網(wǎng)中,用戶通過運行程序?qū)C 上用于分享的文件夾設(shè)置為共享,應(yīng)用程序?qū)⒅鲃訏呙柙撐募A下所有文件,生成文件樹并提交到管理系統(tǒng)中,使用超文本傳輸協(xié)議(HTTP)的形式進(jìn)行共享和展示;對于文件搜索,由主機(jī)提供Web 程序,以網(wǎng)頁形式進(jìn)行交互式操作。其他網(wǎng)絡(luò)用戶可在智能終端使用通用的搜索入口進(jìn)行查詢,若能找到可根據(jù)需要進(jìn)行下載使用。為方便說明,本文將所有使用本系統(tǒng)的電腦終端稱之為客戶端,負(fù)責(zé)承擔(dān)搜索任務(wù)的電腦終端稱為服務(wù)器端。服務(wù)器端承擔(dān)的搜索任務(wù)可以通過使用與客戶端相同的體系來實現(xiàn)。具體工作流程圖如圖1 所示。
圖1 總體流程圖
本文系統(tǒng)功能的實現(xiàn),分為客戶端、服務(wù)器端兩部分分別設(shè)計。
根據(jù)客戶端實現(xiàn)的功能,采用模塊化及逐層封裝思想,將文件操作,數(shù)據(jù)庫操作及網(wǎng)絡(luò)操作逐層封裝,具體分為以下幾個類進(jìn)行功能實現(xiàn):FileTools 文件操作類、DbTools 數(shù)據(jù)庫操作類、Monitor 文件改動監(jiān)控類、ClionHttp 服務(wù)類、Config 配置文件。作為與文獻(xiàn)[1]的比較,本文著重改進(jìn)的地方在于DbTools 數(shù)據(jù)庫操作類與Monitor 文件改動監(jiān)控類兩部分的設(shè)計,下面對每個功能類的實現(xiàn)技術(shù)點進(jìn)行說明。
按照系統(tǒng)設(shè)計,客戶端需有能力獲取用戶設(shè)置為共享文件夾下的所有文件及路徑,故在文件操作類FileTools 中實現(xiàn)獲取所有文件的方法,通過逐層遞歸遍歷實現(xiàn)所有文件的記錄,并同時記錄下文件所在具體位置。
for num in range(len(filelist)):
returndirstr +=creatfile.getfilelist(filepath + '/' + filelist[num])
if os.path.isdir(filepath+'/'+filelist[num]):
else:
returnfilestr+=filepath+'/'+filelist[num]+' '
returnstr+=returnfilestr+returndirstr
為了使文件的路徑信息轉(zhuǎn)換為對HTTP 服務(wù)的有效URL 路徑,故在文件操作類中集成URL 轉(zhuǎn)換方法,實現(xiàn)由共享文件夾的相對位置轉(zhuǎn)化為Web 服務(wù)的有效路由信息:
list = list.replace(path, "http://" + str(ip)+ ':' + str(PORT)).spli(t' ')
通過Python 標(biāo)準(zhǔn)庫中字符串替換方法,高效生成HTTP 服務(wù)分享連接。同時為實現(xiàn)獲取客戶端IP 功能,使用UDP 報文頭抓取方法,該方法相比使用標(biāo)準(zhǔn)庫GETIP()等內(nèi)置功能的實現(xiàn)方法,更能高效地在客戶機(jī)用于兩個及以上IP 地址時,自動判別內(nèi)網(wǎng)IP,實現(xiàn)IP 定位功能。
針對客戶端所需的數(shù)據(jù)庫操縱能力,在比較多種實現(xiàn)技術(shù)后,使用對象關(guān)系映射技術(shù)(Object-Relational Mapping,ORM)[8],作為將本體(Ontology)文件存儲到關(guān)系型數(shù)據(jù)庫中的一種可借鑒的方法。通過在數(shù)據(jù)庫和代碼業(yè)務(wù)應(yīng)用層中間加入數(shù)據(jù)持久化層,避免直接對數(shù)據(jù)庫進(jìn)行操作,避免如SQL 注入等常見的Web 攻擊方式,并且通過對數(shù)據(jù)域的對象化,可以方便的進(jìn)行面向?qū)ο蟮臄?shù)據(jù)元操作。將SQL 語句中的關(guān)系型聯(lián)系轉(zhuǎn)化為源類對象之間的交互。
在具體的Python 語言中,類似的ORM 框架有很多種[8][9],如SQLObject、Storm、Peewee 等。針對客戶端的特點,選取Peewee 的Python ORM 框架,簡單小巧,且容易學(xué)習(xí)。
由于客戶端向服務(wù)器端提交數(shù)據(jù),故設(shè)計數(shù)據(jù)庫表如下:
time 提交時間
ip 提交內(nèi)網(wǎng)IP name 文件名稱
filename http 分享連接
使用Peewee 建立數(shù)據(jù)表模型:
class ip_file_url(BaseModel):
time=CharField()
ip=CharField()
name=CharField()
filename=CharField(max_length=500)
針對客戶端具體功能要求,實現(xiàn)了對數(shù)據(jù)庫的增、刪功能。通過調(diào)用FILETOOLS 模塊獲得文件的名稱和HTTP 分享路徑,轉(zhuǎn)換成具體的數(shù)據(jù)庫條目,并調(diào)用Peewee 中的insert_many()方法,插入到服務(wù)器端數(shù)據(jù)表中。針對共享目錄下文件修改或文件增加、刪除問題,統(tǒng)一使用數(shù)據(jù)表刪除方法,刪除掉本IP 提交的所有信息,并將新的文件共享項目表提交到服務(wù)器數(shù)據(jù)庫中。通過這種方法,來實現(xiàn)對共享條目的動態(tài)修改和對無效信息的及時清除,減少數(shù)據(jù)冗余。
在文件分布式分揀存儲系統(tǒng)中,最重要的是實現(xiàn)文件信息的動態(tài)更新。因為在實際使用中,用戶可能會對文件進(jìn)行不定時的更新,為了保證數(shù)據(jù)的實時性及在整個文件分享系統(tǒng)中的可靠性,就需要實現(xiàn)對特定文件夾的實時監(jiān)控。當(dāng)用戶對分享文件夾中的文件進(jìn)行操作時,系統(tǒng)要及時更新系統(tǒng)數(shù)據(jù)庫中文件樹,來保證數(shù)據(jù)完整性。在開發(fā)中為了保證跨平臺及兼容性,通過封裝系統(tǒng)信號量監(jiān)控機(jī)制,來實現(xiàn)對不同平臺(包括Windows、Linux、Mac OS 等)的文件操作的實時監(jiān)控。
具體而言,使用Python 編程,通過對watchdog 模塊的擴(kuò)展來實現(xiàn),用來監(jiān)控指定目錄/文件的變化:
watchdog.events.FileCreatedEvent()
文件被創(chuàng)建時觸發(fā)該事件
watchdog.events.DirCreatedEvent()
目錄被創(chuàng)建時觸發(fā)該事件
watchdog.events.FileDeletedEvent()
文件被刪除時觸發(fā)該事件
watchdog.events.DirDeletedEvent()
目錄被刪除時觸發(fā)該事件
watchdog.events.FileModifiedEvent()
文件被修改時觸發(fā)該事件(修改文件內(nèi)容、修改文件inode 信息如權(quán)限和訪問時間,都會觸發(fā)該事件)
watchdog.events.DirModifiedEvent()
目錄被修改時觸發(fā)該事件
通過對watchdog 事件處理類的重構(gòu)及繼承,來實現(xiàn)針對文件共享目錄的實時監(jiān)控,每當(dāng)有文件操作發(fā)生在設(shè)定的共享目錄時,系統(tǒng)就能根據(jù)具體的文件操作類型,實時掃描文件修改,并通過FileTools 及Db-Tools 實時同步到服務(wù)器端數(shù)據(jù)庫中。
因為客戶端要根據(jù)需求,使用HTTP 服務(wù)分享客戶端文件,又要降低對系統(tǒng)的負(fù)荷,減小對CPU 及磁盤I/O 影響,故使用Python 標(biāo)準(zhǔn)庫中自帶的http.server模塊,實現(xiàn)了一個小型、符合預(yù)期的HTTP 服務(wù)程序。
WEBDIR=path
PORT=config.http_prot
os.chdir(WEBDIR)
Handler=SimpleHTTPRequestHandler
with socketserver.TCPServer(('', PORT), Handler)as httpd:
print("serving at port",PORT)
httpd.serve_forever()
通過os.chdir()方法,將當(dāng)前路徑切換到設(shè)定的共享文件目錄上,來實現(xiàn)HTTP 服務(wù)的高效運行。
通過創(chuàng)建Config 文件,將一些需要根據(jù)情境來更改的屬性綁定到一起,減少修改代碼的復(fù)雜性,當(dāng)用戶在自行部署時,可以統(tǒng)一地在Config 文件中修改具體參數(shù),如數(shù)據(jù)庫賬號信息、開放端口信息等,避免對代碼的文正行的修改和破壞[10]。
服務(wù)器端需要給用戶提供一個完善的UI 交互界面,滿足用戶的可視化操作要求,結(jié)合本系統(tǒng)的應(yīng)用需求,決定使用Web Server 形式提供給用戶類似搜索引擎的文件查詢界面。針對本項目,建立了一個名為server 的Django App 應(yīng)用。
建立數(shù)據(jù)層
class files(models.Model):
time=models.CharField(max_length=100)
ip=models.CharField(max_length=100)
name=models.CharField(max_length=500)
filename=models.CharField(max_length=500)
class Meta:
db_table='ip_file_url'
來定義數(shù)據(jù)操縱的表結(jié)構(gòu),為后續(xù)數(shù)據(jù)操作實現(xiàn)類定義。
定義兩個方法Headhtml(),Inquire()來完成系統(tǒng)操作。Headhtml()來完成用戶訪問本系統(tǒng)時,返回查詢首頁面的功能,當(dāng)用戶在窗口中輸入要查詢的文件名稱時,通過post 方式提交到后臺,而Inquire()方法用來接受用戶的查詢參數(shù),并使用models 中定義的數(shù)據(jù)表進(jìn)行對數(shù)據(jù)庫的查詢操作。
class MyFormView(View):
form_class=MyForm
template_name='result.html'
def post(self,request,*args,**kwargs):
form=self.form_class(request.POST)
if form.is_valid():
form=files.objects.filter(name_iexact=names)
return render(request, self.template_name, {'form':form})
當(dāng)在數(shù)據(jù)庫中查詢到具體條目時,主動渲染到result 模板中,并返回給用戶。
針對網(wǎng)絡(luò)安全問題,尤其是在表單提交時的跨域攻擊問題,特地在網(wǎng)頁模板中添加{%csrf_token%}標(biāo)簽,使用{%csrf_token%}生成一個input 框在form 表單中提交,每次post 請求提交有需要Django 生成的csrftoken 值,來防范跨域攻擊問題。
在同一局域網(wǎng)中的多臺辦公電腦上進(jìn)行了系統(tǒng)測試,其中一臺電腦啟動服務(wù)器端服務(wù)。圖2 和圖3 分別顯示在客戶端電腦進(jìn)行文件搜索及找到相關(guān)文件后的畫面,可以看到本文系統(tǒng)的實現(xiàn)效果如圖2。
圖2 文件搜索
圖3 文件下載
本文使用Python 語言編程,實現(xiàn)了整個分布式文件共享系統(tǒng)的功能,優(yōu)化設(shè)計的地方主要有:通過寫入數(shù)據(jù)庫表的形式,實現(xiàn)對分享條目的動態(tài)修改和對無效信息的及時清除,減少數(shù)據(jù)冗余,保證信息的準(zhǔn)確性。使用系統(tǒng)監(jiān)控機(jī)制,實現(xiàn)針對常見系統(tǒng)平臺的動態(tài)監(jiān)控,使得該共享方式適用于各種系統(tǒng)平臺。用戶只需要運行客戶端程序,隨時都可以加入到文件共享的隊伍中,其他的網(wǎng)絡(luò)用戶通過搜索,即可獲取相應(yīng)的文件。該方式實現(xiàn)簡單有效,可滿足于各種辦公、教學(xué)環(huán)境使用,是一種可推廣的文件共享方式。
算法過程簡潔明了,易于理解。系統(tǒng)實現(xiàn)部分給出了較直觀的圖,顯示了系統(tǒng)運行時的共享文件搜索及文件下載界面。關(guān)于系統(tǒng)安全[11]及文件搜索過程中模糊查詢、內(nèi)容查詢等細(xì)化方面的工作,可作為下一步的研究方向。