Python09作業思路及源碼:高級FTP伺服器開發(僅供參考)

来源:http://www.cnblogs.com/chensiqiqi/archive/2016/12/29/6231486.html
-Advertisement-
Play Games

高級FTP伺服器開發 一,作業要求 高級FTP伺服器開發 二,程式文件清單 Folder目錄:用戶文件目錄 bin目錄:程式啟動文件目錄 conf目錄:用戶配置文件目錄 core目錄:程式核心代碼目錄 log目錄:程式日誌文件目錄 三,程式流程簡圖 四,程式測試樣圖 創建賬戶 用戶登錄 基本操作 五 ...


高級FTP伺服器開發

一,作業要求

高級FTP伺服器開發

  1. 用戶加密認證(完成)
  2. 多用戶同時登陸(完成)
  3. 每個用戶有不同家目錄且只能訪問自己的家目錄(完成)
  4. 對用戶進行磁碟配額,不同用戶配額可不同(完成)
  5. 用戶登錄server後,可切換目錄(完成)
  6. 查看當前目錄下文件(完成)
  7. 上傳下載文件保持文件一致性(完成)
  8. 傳輸過程中實現進度條(完成)
  9. 可以創建或刪除目錄及文件(完成)
  10. 支持斷點續傳(未做)

二,程式文件清單

  • Folder目錄:用戶文件目錄
  • bin目錄:程式啟動文件目錄
  • conf目錄:用戶配置文件目錄
  • core目錄:程式核心代碼目錄
  • log目錄:程式日誌文件目錄

三,程式流程簡圖

 

四,程式測試樣圖

  • 創建賬戶

 

  • 用戶登錄

 

  • 基本操作

 

 

 

五,核心源碼清單

  • 客戶端核心源碼
  1 #!usr/bin/env python
  2 # -*- coding:utf-8 -*-
  3 # auther:Mr.chen
  4 # 描述:
  5 
  6 import socket,os
  7 import time,json
  8 
  9 
 10 DIR = os.path.dirname(os.path.abspath(__file__))
 11 DIR = DIR.replace('core','Folder/')
 12 HOST = 'localhost'
 13 PORT = 8888
 14 
 15 
 16 
 17 
 18 def ls_Method(s):
 19     s.send("Begin!")
 20     data = ''
 21     while True:
 22         buffer = s.recv(1024)
 23         if buffer == 'Exit!':
 24             break
 25         if not buffer:
 26             print ("伺服器傳輸錯誤!")
 27             return
 28         data += buffer
 29     print (data)
 30 
 31 
 32 def put_Method(s,action,filename):
 33     if os.path.exists(DIR+filename) and os.path.isdir(DIR+filename) == False:
 34         with open(DIR+filename,'r') as f:
 35             data = f.read()
 36         data_size = len(data)
 37         s.send(str(data_size))
 38         if s.recv(1024) == 'OK!':
 39             s.send(filename)
 40             if s.recv(1024) == 'OK!':
 41                 print ("文件開始上傳,請稍後...")
 42                 with open(DIR+filename,'r') as f:
 43                     Num = None
 44                     data = ''
 45                     while True:
 46                         buffer = f.read(1024)
 47                         if not buffer:
 48                             s.send("Exit!")
 49                             break
 50                         s.send(buffer)
 51                         data += buffer
 52                         Num = download_Progress(data_size, len(data), Num)
 53                 if s.recv(1024) == 'OK!':
 54                     print ("上傳成功!磁碟配額剩餘{0}M".format(s.recv(1024)))
 55                 else:
 56                     print ("文件傳輸有損,請重新上傳!")
 57             else:
 58                 print ("不能上傳!伺服器上已有重名的文件")
 59         else:
 60             print ("磁碟配額已滿,請清理磁碟空間!")
 61     else:
 62         s.send("False!")
 63         print ("上傳失敗,沒有這個文件或目標是個文件夾")
 64 
 65 
 66 def get_Method(s,action,filename):
 67     s.send(filename)
 68     print ("正在下載,請等待...")
 69     data = ''
 70     data_size = s.recv(1024)
 71     if data_size == "Flase!":
 72         print ("下載失敗!伺服器沒有找到或目標是個文件夾")
 73         return
 74     data_size = int(data_size)
 75     Num = None
 76     while True:
 77         buffer = s.recv(1024)
 78         if not buffer :
 79             print ("文件損壞,請重新下載!")
 80             break
 81         data += buffer
 82         Num = download_Progress(data_size,len(data),Num)
 83         if data_size == len(data):
 84             with open(DIR + filename, 'w') as f:
 85                 f.write(data)
 86                 print ("下載成功!")
 87                 break
 88 
 89 
 90 def cd_Method(s,action,filename):
 91     s.send(filename)
 92     re = s.recv(1024)
 93     if re == 'OK!':
 94         print ("命令執行成功!")
 95     elif re == 'NULL!':
 96         print ("已到根目錄,不能繼續返回!")
 97     else:
 98         print ("目錄沒有找到!")
 99 
100 
101 def mkdir_Method(s,action,filename):
102     s.send(filename)
103     if s.recv(1024) == 'OK!':
104         print ("目錄創建成功!")
105     else:
106         print ("已有同名目錄或文件!")
107 
108 
109 def rm_Method(s,action,filename):
110     s.send(filename)
111     re = s.recv(1024)
112     if re == "OK!":
113         print ("刪除成功!磁碟配額剩餘{0}M".format(s.recv(1024)))
114     elif re == "DIR!":
115         while True:
116             decide = raw_input("您選擇的目標是個文件夾,是否遞歸刪除(y/n):")
117             if decide == 'y':
118                 s.send("OK!")
119                 re = s.recv(1024)
120                 if re == "OK!":
121                     print ("刪除成功,磁碟配額剩餘{0}M".format(s.recv(1024)))
122                     break
123                 else:
124                     print ("刪除失敗,原因未知!")
125                     break
126             elif decide == 'n':
127                 s.send("False!")
128                 break
129             else:
130                 print ("您的輸入有誤!")
131     else:
132         print ("沒有這個文件")
133 
134 
135 def download_Progress(size_total,size,Num):
136     num = size * 100 / size_total
137     if Num == None:
138         # print (str(num)+"%")
139         print "\r%d" % num,
140         time.sleep(0.01)
141         return num
142     elif num == Num:
143         return num
144     else:
145         print "\r%d" % num,
146         time.sleep(0.01)
147         return num
148 
149 
150 
151 
152 def MD5(password):
153     """
154     加密函數
155     :param password:
156     :return:
157     """
158     import hashlib
159     return hashlib.md5(password).hexdigest()
160 
161 
162 def File_transfer(s):
163     """
164     用戶指令函數
165     :param s:
166     :return:
167     """
168 
169     while True:
170         command = raw_input("請輸入你想執行的命令>>")
171         if not command:
172             continue
173         if command.lower().strip() == 'help':
174             text = """
175                     請用'put'+'空格'+'文件名'的格式上傳文件
176                     請用'get'+'空格'+'文件名'的格式下載文件
177                     請用'cd'+'空格'+'目錄名'的格式進入家目錄下的子文件夾
178                     請用'cd'+'空格'+'..'的格式返回上級目錄
179                     請用'mkdir'+'空格'+'目錄名'的格式進入家目錄的文件夾
180                     請用'rm'+'空格'+'文件名/目錄名'的格式刪除家目錄下的文件
181                     輸入'ls'查看用戶伺服器家目錄
182             """
183             print (text)
184             continue
185         try:
186             action,filename = command.strip().split()
187             action = action.lower()
188         except:
189             if command.lower().strip() == 'ls':
190                 s.send('ls')
191                 print ("正在查詢,請稍後...")
192                 if s.recv(1024) == 'OK!':
193                     ls_Method(s)
194             else:
195                 print ("您的輸入有誤!輸入help查看幫助文檔")
196                 continue
197         else:
198             s.send(action)
199             if s.recv(1024) == 'OK!':
200                 eval(action+'_Method')(s,action,filename)
201             else:
202                 print ("您的輸入有誤!輸入help查看幫助文檔")
203 
204 
205 def Login(s):
206     """
207     用戶登錄
208     :param s:
209     :return:
210     """
211     while True:
212         name = raw_input("請輸入你的登陸名:").strip()
213         password = raw_input("請輸入你的密碼:").strip()
214         if not name or not password:
215             print ("用戶名和密碼不能為空!")
216             continue
217         password = MD5(password)   #密碼加密
218         data = [name,password]
219         s.send(json.dumps(data))
220         if s.recv(1024) == 'OK!':
221             print ("用戶登陸成功!")
222             File_transfer(s)
223         else:
224             print ("用戶登陸失敗!")
225 
226 
227 def Main():
228     """
229     用戶登陸
230     :param s:
231     :param log:
232     :return:
233     """
234     s = socket.socket()
235     try:
236         s.connect((HOST, PORT))
237         s.send("Ready!")
238 
239         data = s.recv(1024)  #接收伺服器歡迎信息
240         if not data:
241             print ("伺服器異常!")
242         else:
243             print (data)
244             Login(s)
245     except Exception,e:
246         print "伺服器連接不上....", e
247     finally:
248         s.close()
249 
250 
251 if __name__ == "__main__":
252     Main()
  • 伺服器端核心源碼
  1 #!usr/bin/env python
  2 # -*- coding:utf-8 -*-
  3 # auther:Mr.chen
  4 # 描述:
  5 
  6 import SocketServer
  7 import os,time,sys,json
  8 import admin_configure
  9 DIR = os.path.dirname(os.path.abspath(__file__))
 10 DIR = DIR.replace('core','Folder/')
 11 
 12 
 13 
 14 class Myserver(SocketServer.BaseRequestHandler):
 15 
 16     def __init__(self,request,client_address,server):
 17         SocketServer.BaseRequestHandler.__init__(self,request,client_address,server)
 18         self.Name = ''          #用戶名
 19         self.Password = ''      #用戶密碼
 20         self.Quota = ''         #用戶磁碟配額
 21         self.Home_path = ''     #用戶家目錄路徑
 22         self.Current_path = ''  #用戶當前路徑
 23         self.DIR = []           #用戶進入過的子目錄列表
 24 
 25 
 26 
 27     def ls_Method(self):
 28         data = self.request.recv(1024)
 29         if data == 'Begin!':
 30             data = os.popen('ls'+' '+self.Current_path).read()
 31             self.request.sendall(data)
 32             time.sleep(0.5)
 33             self.request.send("Exit!")
 34 
 35 
 36     def put_Method(self):
 37         data_size = self.request.recv(1024)
 38         if data_size == 'False!':
 39             return
 40         if int(self.Quota) >= int(data_size):
 41             self.request.send("OK!")
 42             filename = self.request.recv(1024)
 43             if os.path.exists(self.Current_path+filename) == False:
 44                 self.request.send("OK!")
 45                 data = ''
 46                 while True:
 47                     buffer = self.request.recv(1024)
 48                     if buffer == 'Exit!':
 49                         break
 50                     if not buffer:
 51                         break
 52                     data += buffer
 53                 self.Quota = str(int(self.Quota) - len(data))
 54                 dict = admin_configure.config_read(self.Name)
 55                 dict['Quota'] = self.Quota
 56                 admin_configure.config_write(dict)
 57                 with open(self.Current_path+filename,'w') as f:
 58                     f.write(data)
 59                 if len(data) == int(data_size):
 60                     self.request.send("OK!")
 61                     time.sleep(0.25)
 62                     Quota = str(float(self.Quota)/1000000)
 63                     self.request.send(Quota)
 64                 else:
 65                     self.request.send("Flase!")
 66             else:
 67                 self.request.send("False!")
 68         else:
 69             self.request.send("Flase!")
 70 
 71 
 72 
 73     def get_Method(self):
 74         filename = self.request.recv(1024)
 75         if os.path.exists(self.Current_path+filename) and os.path.isdir(self.Current_path+filename) == False:
 76             with open(self.Current_path+filename,'r') as f:
 77                 data = f.read()
 78                 self.request.send(str(len(data)))
 79                 time.sleep(0.5)
 80                 self.request.sendall(data)
 81         else:
 82             self.request.send("Flase!")
 83 
 84 
 85 
 86 
 87 
 88     def cd_Method(self):
 89         filename = self.request.recv(1024)
 90         if filename == '..':
 91             if len(self.DIR) == 0:
 92                 self.request.send("NULL!")
 93                 return
 94             else:
 95                 # self.Current_path = self.Current_path.replace('/'+self.DIR[0]+'/','/')
 96                 list = self.Current_path.split('/')
 97                 del  list[0]
 98                 del list[len(list) - 1]
 99                 del list[len(list) - 1]
100                 str = '/'
101                 for i in range(len(list)):
102                     str = str + list[i] + '/'
103                 self.Current_path = str
104                 del self.DIR[0]
105                 self.request.send("OK!")
106         elif os.path.isdir(self.Current_path+filename):
107                 self.Current_path = self.Current_path + filename + '/'
108                 self.DIR.insert(0,filename)
109                 self.request.send("OK!")
110         else:
111             self.request.send("False!")
112 
113 
114     def mkdir_Method(self):
115         filename = self.request.recv(1024)
116         if os.path.exists(self.Current_path+filename):
117             self.request.send("False!")
118         else:
119             os.system("mkdir -p " + self.Current_path + filename)
120             if os.path.exists(self.Current_path + filename):
121                 self.request.send("OK!")
122             else:
123                 self.request.send("False!")
124 
125     def rm_Method(self):
126         filename = self.request.recv(1024)
127         if os.path.exists(self.Current_path+filename):
128             if os.path.isdir(self.Current_path+filename):
129                 self.request.send("DIR!")
130                 if self.request.recv(1024) == "OK!":
131                     data = os.popen('du'+' '+ '-sk' + ' ' + self.Current_path+filename).read()
132                     data_size,file = data.strip().split()
133                     os.system("rm -rf " + self.Current_path + filename)
134                     self.Quota = str(int(self.Quota) + int(data_size))
135                     dict = admin_configure.config_read(self.Name)
136                     dict['Quota'] = self.Quota
137                     admin_configure.config_write(dict)
138                     self.request.send("OK!")
139                     time.sleep(0.25)
140                     Quota = str(float(self.Quota) / 1000000)
141                     self.request.send(Quota)
142 
143                 else:
144                     return
145             else:
146                 with open(self.Current_path+filename,'r') as f:
147                     data = f.read()
148                 os.system("rm -f " + self.Current_path + filename)
149                 self.Quota = str(int(self.Quota) + len(data))
150                 dict = admin_configure.config_read(self.Name)
151                 dict['Quota'] = self.Quota
152                 admin_configure.config_write(dict)
153                 self.request.send("OK!")
154                 time.sleep(0.25)
155                 Quota = str(float(self.Quota) / 1000000)
156                 self.request.send(Quota)
157         else:
158             self.request.send("False!")
159 
160     def Login_Method(self,data):
161         re = admin_configure.config_read(data[0])
162         if re == None:
163             return False
164         else:
165             if re['Password'] == data[1]:
166                 self.Name = re['Name']
167                 self.Password = re['Password']
168                 self.Quota = re['Quota']
169                 self.Home_path = re['Home_path']
170                 self.Current_path = re['Current_path']
171                 self.DIR = []
172                 	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 參考資料: http://blog.csdn.net/bitfan/article/details/4438458 所謂記憶體映射文件,其實就是在記憶體中開闢出一塊存放數據的專用區域,這區域往往與硬碟上特定的文件相對應。進程將這塊記憶體區域映射到自己的地址空間中,訪問它就象是訪問普通的記憶體一樣。 在.NE ...
  • 一.母板頁_Layout.cshtml類似於傳統WebForm中的.master文件,起到頁面整體框架重用的目地1.母板頁代碼預覽 2.子頁面標題的設置雖然多個子頁面可以引用同一個母板頁,但不同的頁面標題可以單獨設置。@ViewBag.Title 即是一個標題的占位符,在Control里或頁面中給該 ...
  • 新工作入職不滿半周,目前仍然還在交接工作,適應環境當中,筆者不得不說看別人的源碼實在是令人痛苦。所幸今天終於將大部分工作流暢地看了一遍,接下來就是熟悉框架技術的階段了。 也正是在看源碼的過程當中,有一個比較明顯的用法細節引起了我的註意,我發現一位同事在請求遠程Web Api時,雖然使用了 類,但是在 ...
  • 快速開發相對於其他開發方式有什麼優勢?能為你節省多少成本? ...
  • VS項目中使用Nuget還原包後編譯生產還一直報錯? ...
  • 申請博客 ...
  • 在上一篇C#多線程之線程池篇1中,我們主要學習瞭如何線上程池中調用委托以及如何線上程池中執行非同步操作,在這篇中,我們將學習線程池和並行度、實現取消選項的相關知識。 三、線程池和並行度 在這一小節中,我們將學習對於大量的非同步操作,使用線程池和分別使用單獨的線程在性能上有什麼差異性。具體操作步驟如下: ...
  • 安裝了Visual Studio的那些使用微軟平臺的開發者通常能夠非常容易地操作自己的項目:打開解決方案,修改內容,設置好所有必須的文件以及配置後編譯項目。但是在構建伺服器或者持續交付系統等沒有安裝Visual Studio的環境中,編譯項目和解決方案是非常難的。 對於這一問題,微軟之前給出的方案是 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...