socketserver实现FTP

功能:     1、用户加密认证    2、允许同时多用户登录    3、每个用户有自己的家目录 ,且只能访问自己的家目录    4、对用户进行磁盘配额,每个用户的可用空间不同    5、允许用户在ftp server上随意切换目录    6、允许用户查看当前目录下文件    7、允许上传和下载文件,保证文件一致性    8、文件传输过程中显示进度条    附加功能:支持文件的断点续传

环境:  python 3.5

特性:  用socketserver实现FTP

主要功能实现:  1、用户加密认证    ConfigParser 是Python自带的模块, 用来读写配置文件,将用户信息以下边的格式存入account.py文件,读出后进行判断
[DEFAULT]

[alex]
Password = 123456
Quotation = 100

[jack]
Password = 123456
Quotation = 100
    2、允许同时多用户登录      从scokerserver 继承 socketserver.ThreadingTCPServer即可实现
    3、每个用户有自己的家目录 ,且只能访问自己的家目录      将所有路径封装在home目录下
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

USER_HOME = ‘%s\home‘ % BASE_DIR
LOG_DIR = ‘%s\log‘ % BASE_DIR
LOG_LEVEL = ‘DEBUG‘
    4、允许用户在ftp server上随意切换目录      用os模块改变工作目录
os.chdir(func_val)
    5、允许用户查看当前目录下文件      用os模块的os.listdir,下为server端代码
    def _ls(self,*args,**kwargs):
        ‘‘‘显示当前目录下的所有文件‘‘‘
        if os.getcwd() == ‘%s\\bin‘% settings.BASE_DIR:
            user_home_dir = "%s\%s" % (settings.USER_HOME, self.user["Username"])
            self.request.send(json.dumps(os.listdir(user_home_dir)).encode())
        else:self.request.send(json.dumps(os.listdir()).encode())
    6、允许上传和下载文件,保证文件一致性      判断上传和下载的文件在传输前后的大小,用以判断文件是否保持一致

  1 #server端
  2 #
  3     def _put(self,*args,**kwargs):
  4         ‘‘‘上传文件命令‘‘‘
  5         data = args[0]
  6
  7         response = self.get_response()
  8         if response["status_code"] == 257:  # ready to receive
  9             self.request.send(b‘1‘)  # send confirmation to server
 10             user_home_dir = "%s\%s" % (settings.USER_HOME, self.user["Username"])
 11             base_filename = "%s\%s" % (user_home_dir, data.get(‘filename‘))
 12             received_size = 0
 13             file_obj = open(base_filename, ‘wb‘)
 14             if data.get(‘md5‘):
 15                 md5_obj = hashlib.md5()
 16                 while received_size < response[‘file_size‘]:
 17                     line = self.request.recv(4096)
 18                     received_size += len(line)
 19                     file_obj.write(line)
 20                     md5_obj.update(line)
 21                 else:
 22                     file_obj.close()
 23                     md5_val = md5_obj.hexdigest()
 24                     self.send_response(258, {‘md5‘: md5_val})
 25                     print("-----file rece done-----")
 26
 27             else:
 28                 while received_size < response[‘file_size‘]:
 29                     data = self.request.recv(4096)
 30                     received_size += len(data)
 31                     file_obj.write(data)
 32                 else:
 33                     print("-----file rece done-----")
 34                     file_obj.close()
 35         else:
 36             print(STATUS_CODE[response["status_code"]])
 37
 38
 39     def _get(self,*args,**kwargs):
 40         ‘‘‘下载文件命令‘‘‘
 41         data = args[0]
 42         if data.get(‘filename‘) is None:
 43             self.send_response(255)
 44         user_home_dir = "%s\%s" %(settings.USER_HOME,self.user["Username"])
 45         file_abs_path = "%s\%s" %(user_home_dir,data.get(‘filename‘))
 46         print("file abs path",file_abs_path)
 47
 48         if os.path.isfile(file_abs_path):
 49             file_obj = open(file_abs_path,‘rb‘)
 50             file_size = os.path.getsize(file_abs_path)
 51             self.send_response(257,data = {‘file_size‘:file_size})
 52             self.request.recv(1)    #等待客户端确认,防粘包
 53
 54             if data.get(‘md5‘):
 55                 md5_obj = hashlib.md5()
 56                 for line in file_obj:
 57                     self.request.send(line)
 58                     md5_obj.update(line)
 59                 else:
 60                     file_obj.close()
 61                     md5_val = md5_obj.hexdigest()
 62                     self.send_response(258,{‘md5‘:md5_val})
 63                     print("send file done...")
 64             else:
 65                 for line in file_obj:
 66                     self.request.send(line)
 67                 else:
 68                     file_obj.close()
 69                     print("send file done...")
 70         else:
 71             self.send_response(256)
 72
 73
 74
 75
 76 # client端
 77 #
 78     def _get(self,cmd_list):
 79         ‘‘‘下载文件‘‘‘
 80         print("get--",cmd_list)
 81         if len(cmd_list) == 1:
 82             print("no filename follows...")
 83             return
 84         data_header = {
 85             ‘action‘:‘get‘,
 86             ‘filename‘:cmd_list[1]
 87         }
 88         if self.__md5_required(cmd_list):
 89             data_header[‘md5‘] = True
 90
 91         self.sock.send(json.dumps(data_header).encode())
 92         response = self.get_response()
 93         print(response)
 94         try:
 95             if response["status_code"] == 257:#ready to receive
 96                 self.sock.send(b‘1‘) #send confirmation to server
 97                 base_filename = cmd_list[1].split(‘/‘)[-1]
 98                 received_size = 0
 99                 file_obj = open(base_filename,‘wb‘)
100                 if self.__md5_required(cmd_list):
101                     md5_obj = hashlib.md5()
102                     progress = self.show_progress(response[‘file_size‘]) #generator
103                     progress.__next__()
104                     while received_size < response[‘file_size‘]:
105                         data = self.sock.recv(4096)
106                         received_size += len(data)
107                         try:
108                             progress.send(len(data))
109                         except StopIteration as e:
110                             print("100%")
111                         file_obj.write(data)
112                         md5_obj.update(data)
113                     else:
114                         print("-----file rece done-----")
115                         file_obj.close()
116                         md5_val = md5_obj.hexdigest()
117                         md5_from_server = self.get_response()
118                         if md5_from_server[‘status_code‘] == 258:
119                             if md5_from_server[‘md5‘] == md5_val:
120                                 print("%s 文件一致性校验成功!"% base_filename)
121                         print(md5_val,md5_from_server)
122
123                 else:
124                     progress = self.show_progress(response[‘file_size‘])  # generator
125                     progress.__next__()
126                     while received_size < response[‘file_size‘]:
127                         data = self.sock.recv(4096)
128                         received_size += len(data)
129                         file_obj.write(data)
130                         try:
131                             progress.send(len(data))
132                         except StopIteration as e:
133                             print("100%")
134                     else:
135                         print("-----file rece done-----")
136                         file_obj.close()
137             else:
138                 print(STATUS_CODE[response["status_code"]])
139         except Exception as e:
140             base_file_size = os.path.getsize(base_filename)
141             with open(‘data\\breakpoint‘, ‘wb‘) as br_po:
142                 data_header[‘action‘] = ‘breakpoint‘
143                 data_header[‘breakpoint‘] = base_file_size
144                 br_po.write(json.dumps(data_header).encode())
145
146
147     def _put(self,cmd_list):
148         ‘‘‘上传文件‘‘‘
149         print("put--", cmd_list)
150         if len(cmd_list) == 1:
151             print("no filename follows...")
152             return
153         data_header = {
154             ‘action‘: ‘put‘,
155             ‘filename‘: cmd_list[1]
156         }
157         if self.__md5_required(cmd_list):
158             data_header[‘md5‘] = True
159
160         self.sock.send(json.dumps(data_header).encode())
161         if os.path.isfile(cmd_list[1]):
162             file_obj = open(cmd_list[1], ‘rb‘)
163             file_size = os.path.getsize(cmd_list[1])
164             self.send_response(257, data={‘file_size‘: file_size})
165             self.sock.recv(1)  # 等待服务器端确认
166             if self.__md5_required(cmd_list):
167                 md5_obj = hashlib.md5()
168                 progress = self.show_progress(file_size)  # generator
169                 progress.__next__()
170                 for line in file_obj:
171                     self.sock.send(line)
172                     try:
173                         progress.send(len(line))
174                     except StopIteration as e:
175                         print("100%")
176                     md5_obj.update(line)
177                 else:
178                     file_obj.close()
179                     md5_val = md5_obj.hexdigest()
180                     md5_from_server = self.get_response()
181                     if md5_from_server[‘md5‘] == md5_val:
182                             print("%s 文件一致性校验成功!"% cmd_list[1])
183                     self.send_response(258, {‘md5‘: md5_val})
184                     print("send file done...")
185             else:
186                 progress = self.show_progress(file_size)  # generator
187                 progress.__next__()
188                 for line in file_obj:
189                     self.sock.send(line)
190                     try:
191                         progress.send(len(line))
192                     except StopIteration as e:
193                         print("100%")
194                 else:
195                     file_obj.close()
196                     print("send file done...")
197         else:
198             print(256)

get and put

    7、文件传输过程中显示进度条      根据已传文件大小和总文件大小比对判断,输出符号

 1     def show_progress(self,total):
 2         ‘‘‘显示进度条
 3            total: 文件大小‘‘‘
 4         received_size = 0
 5         current_percent = 0
 6         while received_size < total:
 7             if int((received_size / total) * 100) > current_percent:
 8                 print(">",end=‘‘,flush=True)
 9                 current_percent = int((received_size / total) * 100)
10             new_size = yield
11             received_size += new_size

进度条

    附加功能:支持文件的断点续传      将上次断点信息记录下来,也就是记录已传文件大小,再次启用时,将目标文件光标移到上次断点处,然后进行续传

 1     def _breakpoint(self,*args,**kwargs):
 2         ‘‘‘断点续传‘‘‘
 3         data = args[0]
 4         if data.get(‘filename‘) is None:
 5             self.send_response(255)
 6         user_home_dir = "%s\%s" % (settings.USER_HOME, self.user["Username"])
 7         file_abs_path = "%s\%s" % (user_home_dir, data.get(‘filename‘))
 8         print("file abs path", file_abs_path)
 9         print(data.get(‘breakpoint‘))
10
11         if os.path.isfile(file_abs_path):
12             file_obj = open(file_abs_path, ‘rb‘)
13             file_obj.seek(data.get(‘breakpoint‘))
14             file_size = os.path.getsize(file_abs_path)
15             self.send_response(257, data={‘file_size‘: file_size})
16             self.request.recv(1)  # 等待客户端确认
17
18             if data.get(‘md5‘):
19                 md5_obj = hashlib.md5()
20                 for line in file_obj:
21                     self.request.send(line)
22                     md5_obj.update(line)
23                 else:
24                     file_obj.close()
25                     md5_val = md5_obj.hexdigest()
26                     self.send_response(258, {‘md5‘: md5_val})
27                     print("send file done...")
28             else:
29                 for line in file_obj:
30                     self.request.send(line)
31                 else:
32                     file_obj.close()
33                     print("send file done...")
34         else:
35             self.send_response(256)
36         pass

breakpoint

   主要知识点:

    类的继承    os模块的应用    json模块的应用    类方法的运用    md5加密方法    scoket链接    scoketserver链接    反射    异常处理

小结:          这个程序主要用socketserver实现了一台服务器链接多个客户端,并且进行信息交互,并且实现了几个简单的功能,如:get 文件下载、put 上传文件、cd 切换目录、ls 查看文件、breakpoint断点续传。

主要代码:

  1 #server端
  2 #
  3
  4
  5 import os,sys
  6 import hashlib
  7 import socket
  8 import socketserver
  9 import json
 10 import configparser
 11 from conf import settings
 12
 13
 14 STATUS_CODE = {
 15     250 : "Invalid cmd format,e.g:{‘action‘:‘get‘,‘filename‘:‘test.py‘,‘size‘:344",
 16     251 : "Invalid cmd",
 17     252 : "Invalid auth data",
 18     253 : "Wrong username or password..",
 19     254 : "Passed authentication",
 20     255 : "Filename doesn‘t provided",
 21     256 : "File doesn‘t exist on server",
 22     257 : "ready to send file",
 23     258 : "md5 verification",
 24     259 : "Directory has been switched"
 25 }
 26
 27
 28
 29
 30
 31 class FTPHandler(socketserver.BaseRequestHandler):
 32     ‘‘‘定义request handler类,从BaseRequestHandler类继承‘‘‘
 33     def handle(self):
 34         ‘‘‘
 35         获取服务器端的信息
 36         如果传来cd命令,改变工作目录
 37         ‘‘‘
 38
 39         while True:
 40             self.data = self.request.recv(1024).strip()
 41             if not self.data:
 42                 print(‘Client closed..‘)
 43                 break
 44             data = json.loads(self.data.decode())
 45             if data.get(‘action‘) is not None:
 46                 if hasattr(self,‘_%s‘%data.get(‘action‘)):
 47                     func =getattr(self,‘_%s‘%data.get(‘action‘))
 48                     func_val = func(data)
 49                     if data.get(‘action‘) == ‘cd‘:     #cd 命令,改变工作目录
 50                         os.chdir(func_val)
 51                     else:pass
 52                 else:
 53                     print(‘Invalid cmd‘)
 54                     self.send_response(251)
 55             else:
 56                 print(‘Invalid cmd format‘)
 57                 self.send_response(250)
 58
 59
 60     def send_response(self,status_code,data=None):
 61         ‘‘‘向客户端返回数据‘‘‘
 62         response = {‘status_code‘: status_code, ‘status_msg‘:STATUS_CODE[status_code]}
 63         if data:
 64             response.update(data)
 65         self.request.send(json.dumps(response).encode())
 66
 67
 68     def _auth(self,*args,**kwargs):
 69         ‘‘‘判断用户是否输入完整的用户名和密码
 70            验证用户名和密码是否合法‘‘‘
 71         data = args[0]
 72         if data.get(‘username‘) is None or data.get(‘password‘) is None:
 73             self.send_response(252)
 74
 75         user = self.authenticate(data.get(‘username‘),data.get(‘password‘))
 76         if user is None:
 77             self.send_response(253)
 78         else:
 79             print(‘passed authentication‘,user)
 80             self.user = user
 81             self.send_response(254)
 82
 83
 84     def authenticate(self,username,password):       #
 85         ‘‘‘验证用户合法性,合法返回用户数据‘‘‘
 86         config = configparser.ConfigParser()
 87         config.read(settings.ACCOUNT_FILE)
 88         if username in config.sections():
 89             _password = config[username][‘Password‘]
 90             if _password == password:
 91                 print(‘pass auth..‘,username)
 92                 config[username]["Username"] = username
 93                 return config[username]
 94
 95
 96     def get_response(self):
 97         ‘‘‘接收客户端回复结果‘‘‘
 98         data = self.request.recv(1024)
 99         data = json.loads(data.decode())
100         return data
101
102
103     def show_progress(self,total):
104         ‘‘‘显示进度条
105            total: 文件大小‘‘‘
106         received_size = 0
107         current_percent = 0
108         while received_size < total:
109             if int((received_size / total) * 100) > current_percent:
110                 print(">",end=‘‘,flush=True)
111                 current_percent = int((received_size / total) * 100)
112             new_size = yield
113             received_size += new_size
114
115
116     def _put(self,*args,**kwargs):
117         ‘‘‘上传文件命令‘‘‘
118         data = args[0]
119
120         response = self.get_response()
121         if response["status_code"] == 257:  # ready to receive
122             self.request.send(b‘1‘)  # send confirmation to server
123             user_home_dir = "%s\%s" % (settings.USER_HOME, self.user["Username"])
124             base_filename = "%s\%s" % (user_home_dir, data.get(‘filename‘))
125             received_size = 0
126             file_obj = open(base_filename, ‘wb‘)
127             if data.get(‘md5‘):
128                 md5_obj = hashlib.md5()
129                 while received_size < response[‘file_size‘]:
130                     line = self.request.recv(4096)
131                     received_size += len(line)
132                     file_obj.write(line)
133                     md5_obj.update(line)
134                 else:
135                     file_obj.close()
136                     md5_val = md5_obj.hexdigest()
137                     self.send_response(258, {‘md5‘: md5_val})
138                     print("-----file rece done-----")
139
140             else:
141                 while received_size < response[‘file_size‘]:
142                     data = self.request.recv(4096)
143                     received_size += len(data)
144                     file_obj.write(data)
145                 else:
146                     print("-----file rece done-----")
147                     file_obj.close()
148         else:
149             print(STATUS_CODE[response["status_code"]])
150
151
152     def _get(self,*args,**kwargs):
153         ‘‘‘下载文件命令‘‘‘
154         data = args[0]
155         if data.get(‘filename‘) is None:
156             self.send_response(255)
157         user_home_dir = "%s\%s" %(settings.USER_HOME,self.user["Username"])
158         file_abs_path = "%s\%s" %(user_home_dir,data.get(‘filename‘))
159         print("file abs path",file_abs_path)
160
161         if os.path.isfile(file_abs_path):
162             file_obj = open(file_abs_path,‘rb‘)
163             file_size = os.path.getsize(file_abs_path)
164             self.send_response(257,data = {‘file_size‘:file_size})
165             self.request.recv(1)    #等待客户端确认,防粘包
166
167             if data.get(‘md5‘):
168                 md5_obj = hashlib.md5()
169                 for line in file_obj:
170                     self.request.send(line)
171                     md5_obj.update(line)
172                 else:
173                     file_obj.close()
174                     md5_val = md5_obj.hexdigest()
175                     self.send_response(258,{‘md5‘:md5_val})
176                     print("send file done...")
177             else:
178                 for line in file_obj:
179                     self.request.send(line)
180                 else:
181                     file_obj.close()
182                     print("send file done...")
183         else:
184             self.send_response(256)
185
186
187
188     def _ls(self,*args,**kwargs):
189         ‘‘‘显示当前目录下的所有文件‘‘‘
190         if os.getcwd() == ‘%s\\bin‘% settings.BASE_DIR:
191             user_home_dir = "%s\%s" % (settings.USER_HOME, self.user["Username"])
192             self.request.send(json.dumps(os.listdir(user_home_dir)).encode())
193         else:self.request.send(json.dumps(os.listdir()).encode())
194
195
196
197     def _cd(self,*args,**kwargs):
198         ‘‘‘改变工作目录‘‘‘
199         data = args[0]
200         user_home_dir = "%s\%s" % (settings.USER_HOME, self.user["Username"])
201         file_abs_path = "%s\%s" %(user_home_dir,data.get(‘path‘))
202         try:
203             os.listdir(file_abs_path)
204         except FileNotFoundError as e:
205             self.request.send(json.dumps(e).encode())
206             return
207         self.request.send(json.dumps(259).encode())
208         os.chdir(file_abs_path)
209         return file_abs_path
210
211
212     def _breakpoint(self,*args,**kwargs):
213         ‘‘‘断点续传‘‘‘
214         data = args[0]
215         if data.get(‘filename‘) is None:
216             self.send_response(255)
217         user_home_dir = "%s\%s" % (settings.USER_HOME, self.user["Username"])
218         file_abs_path = "%s\%s" % (user_home_dir, data.get(‘filename‘))
219         print("file abs path", file_abs_path)
220         print(data.get(‘breakpoint‘))
221
222         if os.path.isfile(file_abs_path):
223             file_obj = open(file_abs_path, ‘rb‘)
224             file_obj.seek(data.get(‘breakpoint‘))
225             file_size = os.path.getsize(file_abs_path)
226             self.send_response(257, data={‘file_size‘: file_size})
227             self.request.recv(1)  # 等待客户端确认
228
229             if data.get(‘md5‘):
230                 md5_obj = hashlib.md5()
231                 for line in file_obj:
232                     self.request.send(line)
233                     md5_obj.update(line)
234                 else:
235                     file_obj.close()
236                     md5_val = md5_obj.hexdigest()
237                     self.send_response(258, {‘md5‘: md5_val})
238                     print("send file done...")
239             else:
240                 for line in file_obj:
241                     self.request.send(line)
242                 else:
243                     file_obj.close()
244                     print("send file done...")
245         else:
246             self.send_response(256)
247         pass

server端

  1 #client端
  2 #
  3
  4 import socket
  5 import hashlib
  6 import os,json
  7 import optparse
  8 import socketserver
  9
 10
 11 STATUS_CODE = {
 12     250 : "Invalid cmd format,e.g:{‘action‘:‘get‘,‘filename‘:‘test.py‘,‘size‘:344",
 13     251 : "Invalid cmd",
 14     252 : "Invalid auth data",
 15     253 : "Wrong username or password..",
 16     254 : "Passed authentication",
 17     255 : "Filename doesn‘t provided",
 18     256 : "File doesn‘t exist on server",
 19     257 : "ready to send file",
 20     258 : "md5 verification",
 21     259 : "Directory has been switched"
 22 }
 23
 24
 25
 26
 27 class FTPClient(object):
 28     ‘‘‘客户端‘‘‘
 29     def __init__(self):
 30         ‘‘‘用户信息输入格式化
 31             变量定义‘‘‘
 32         parser = optparse.OptionParser()
 33         parser.add_option(‘-s‘, ‘--server‘, dest=‘server‘, help =‘ftp server ip_addr‘)
 34         parser.add_option(‘-p‘,‘--port‘, type=‘int‘, dest=‘port‘, help=‘ftp server port‘)
 35         parser.add_option(‘-U‘, ‘--username‘, dest=‘username‘, help=‘username‘)
 36         parser.add_option(‘-P‘, ‘--Password‘, dest=‘password‘, help=‘password‘)
 37         self.options, self.args = parser.parse_args()
 38         self.verify_args(self.options,self.args)
 39         self.make_connection()
 40
 41
 42     def make_connection(self):
 43         ‘‘‘连接服务器‘‘‘
 44         self.sock = socket.socket()
 45         self.sock.connect((self.options.server,self.options.port))
 46
 47
 48
 49     def verify_args(self,options,args):
 50         ‘‘‘校验参数合法性‘‘‘
 51         if options.username and options.password:
 52             pass
 53         elif options.username is None and options.password is None:
 54             pass
 55         else:
 56             if options.username is None or options.password is None:
 57                 print(‘Error:username and password must be provided together..‘)
 58         if options.server and options.port:
 59             if options.port > 0 and options.port < 65535:
 60                 return True
 61             else:
 62                 exit(‘Err:host port must in 0-65535‘)
 63
 64
 65     def authenticate(self):
 66         ‘‘‘用户验证‘‘‘
 67         if self.options.username:
 68             return self.get_auth_result(self.options.username, self.options.password)
 69         else:
 70             retry_count = 0
 71             while retry_count < 3:
 72                 username = input("username:").strip()
 73                 password = input("password:").strip()
 74                 return self.get_auth_result(username,password)
 75
 76
 77
 78
 79     def get_auth_result(self,user,password):
 80         ‘‘‘用户认证‘‘‘
 81         data = {‘action‘:‘auth‘,
 82                 ‘username‘:user,
 83                 ‘password‘:password}
 84
 85         self.sock.send(json.dumps(data).encode())
 86         response = self.get_response()
 87         if response.get(‘status_code‘) == 254:
 88             print("Passed authentication!")
 89             self.user = user
 90             return True
 91         else:
 92             print(data.get(‘status_msg‘))
 93         print(‘response:‘,data)
 94
 95
 96     def __md5_required(self,cmd_list):
 97         ‘‘‘检测命令是否需要进行MD5验证‘‘‘
 98         if ‘--md5‘ in cmd_list:
 99             return True
100
101
102     def show_progress(self,total):
103         ‘‘‘进度条‘‘‘
104         received_size = 0
105         current_percent = 0
106         while received_size < total:
107             if int((received_size / total) * 100) > current_percent:
108                 print(">",end=‘‘,flush=True)
109                 current_percent = int((received_size / total) * 100)
110             new_size = yield
111             received_size += new_size
112
113
114     def send_response(self,status_code,data=None):
115         ‘‘‘向服务器端返回数据‘‘‘
116         response = {‘status_code‘: status_code, ‘status_msg‘:STATUS_CODE[status_code]}
117         if data:
118             response.update(data)
119         self.sock.send(json.dumps(response).encode())
120
121
122     def get_response(self):
123         ‘‘‘得到服务器端回复结果‘‘‘
124         data = self.sock.recv(1024)
125         data = json.loads(data.decode())
126         return data
127
128
129     def _get(self,cmd_list):
130         ‘‘‘下载文件‘‘‘
131         print("get--",cmd_list)
132         if len(cmd_list) == 1:
133             print("no filename follows...")
134             return
135         data_header = {
136             ‘action‘:‘get‘,
137             ‘filename‘:cmd_list[1]
138         }
139         if self.__md5_required(cmd_list):
140             data_header[‘md5‘] = True
141
142         self.sock.send(json.dumps(data_header).encode())
143         response = self.get_response()
144         print(response)
145         try:
146             if response["status_code"] == 257:#ready to receive
147                 self.sock.send(b‘1‘) #send confirmation to server
148                 base_filename = cmd_list[1].split(‘/‘)[-1]
149                 received_size = 0
150                 file_obj = open(base_filename,‘wb‘)
151                 if self.__md5_required(cmd_list):
152                     md5_obj = hashlib.md5()
153                     progress = self.show_progress(response[‘file_size‘]) #generator
154                     progress.__next__()
155                     while received_size < response[‘file_size‘]:
156                         data = self.sock.recv(4096)
157                         received_size += len(data)
158                         try:
159                             progress.send(len(data))
160                         except StopIteration as e:
161                             print("100%")
162                         file_obj.write(data)
163                         md5_obj.update(data)
164                     else:
165                         print("-----file rece done-----")
166                         file_obj.close()
167                         md5_val = md5_obj.hexdigest()
168                         md5_from_server = self.get_response()
169                         if md5_from_server[‘status_code‘] == 258:
170                             if md5_from_server[‘md5‘] == md5_val:
171                                 print("%s 文件一致性校验成功!"% base_filename)
172                         print(md5_val,md5_from_server)
173
174                 else:
175                     progress = self.show_progress(response[‘file_size‘])  # generator
176                     progress.__next__()
177                     while received_size < response[‘file_size‘]:
178                         data = self.sock.recv(4096)
179                         received_size += len(data)
180                         file_obj.write(data)
181                         try:
182                             progress.send(len(data))
183                         except StopIteration as e:
184                             print("100%")
185                     else:
186                         print("-----file rece done-----")
187                         file_obj.close()
188             else:
189                 print(STATUS_CODE[response["status_code"]])
190         except Exception as e:
191             base_file_size = os.path.getsize(base_filename)
192             with open(‘data\\breakpoint‘, ‘wb‘) as br_po:
193                 data_header[‘action‘] = ‘breakpoint‘
194                 data_header[‘breakpoint‘] = base_file_size
195                 br_po.write(json.dumps(data_header).encode())
196
197
198     def _put(self,cmd_list):
199         ‘‘‘上传文件‘‘‘
200         print("put--", cmd_list)
201         if len(cmd_list) == 1:
202             print("no filename follows...")
203             return
204         data_header = {
205             ‘action‘: ‘put‘,
206             ‘filename‘: cmd_list[1]
207         }
208         if self.__md5_required(cmd_list):
209             data_header[‘md5‘] = True
210
211         self.sock.send(json.dumps(data_header).encode())
212         if os.path.isfile(cmd_list[1]):
213             file_obj = open(cmd_list[1], ‘rb‘)
214             file_size = os.path.getsize(cmd_list[1])
215             self.send_response(257, data={‘file_size‘: file_size})
216             self.sock.recv(1)  # 等待服务器端确认
217             if self.__md5_required(cmd_list):
218                 md5_obj = hashlib.md5()
219                 progress = self.show_progress(file_size)  # generator
220                 progress.__next__()
221                 for line in file_obj:
222                     self.sock.send(line)
223                     try:
224                         progress.send(len(line))
225                     except StopIteration as e:
226                         print("100%")
227                     md5_obj.update(line)
228                 else:
229                     file_obj.close()
230                     md5_val = md5_obj.hexdigest()
231                     md5_from_server = self.get_response()
232                     if md5_from_server[‘md5‘] == md5_val:
233                             print("%s 文件一致性校验成功!"% cmd_list[1])
234                     self.send_response(258, {‘md5‘: md5_val})
235                     print("send file done...")
236             else:
237                 progress = self.show_progress(file_size)  # generator
238                 progress.__next__()
239                 for line in file_obj:
240                     self.sock.send(line)
241                     try:
242                         progress.send(len(line))
243                     except StopIteration as e:
244                         print("100%")
245                 else:
246                     file_obj.close()
247                     print("send file done...")
248         else:
249             print(256)
250
251
252     def _ls(self,*args,**kwargs):
253         ‘‘‘获取当前目录下的所有文件‘‘‘
254         print(‘ls‘.center(30,‘-‘))
255         data_header = {
256             ‘action‘: ‘ls‘,
257         }
258         self.sock.send(json.dumps(data_header).encode())
259         ls_val = self.sock.recv(1024)
260         ls_val = json.loads(ls_val.decode())
261         for obj in ls_val:
262             print(obj)
263
264
265     def _cd(self,cmd_list):
266         ‘‘‘改变工作目录‘‘‘
267         print("cd--", cmd_list)
268         if len(cmd_list) == 1:
269             cmd_list.append(‘‘)
270         data_header = {
271             ‘action‘: ‘cd‘,
272             ‘path‘: cmd_list[1]
273         }
274         self.sock.send(json.dumps(data_header).encode())
275         server_path = self.sock.recv(1024)
276         server_path = json.loads(server_path.decode())
277         if server_path == 259 :
278             print("%s >" % cmd_list[1],end=‘‘)
279
280
281     def _breakpoint(self,*args,**kwargs):
282         ‘‘‘断点续传‘‘‘
283         with open(‘data\\breakpoint‘, ‘rb‘) as br_po:
284             data_header = json.loads(br_po.read().decode())
285             br_po.close()
286         if data_header:
287             print(data_header)
288             self.sock.send(json.dumps(data_header).encode())
289             response = self.get_response()
290             try:
291                 if response["status_code"] == 257:  # ready to receive
292                     self.sock.send(b‘1‘)  # send confirmation to server
293                     base_filename = data_header[‘filename‘].split(‘/‘)[-1]
294                     received_size = data_header[‘breakpoint‘]
295                     file_obj = open(base_filename, ‘ab‘)
296                     file_obj.seek(data_header[‘breakpoint‘])
297                     if self.__md5_required(data_header):
298                         md5_obj = hashlib.md5()
299                         progress = self.show_progress(response[‘file_size‘])  # generator
300                         progress.__next__()
301                         while received_size < response[‘file_size‘]:
302                             data = self.sock.recv(4096)
303                             received_size += len(data)
304                             try:
305                                 progress.send(len(data))
306                             except StopIteration as e:
307                                 print("100%")
308                             file_obj.write(data)
309                             md5_obj.update(data)
310                         else:
311                             print("-----file rece done-----")
312                             file_obj.close()
313                             md5_val = md5_obj.hexdigest()
314                             md5_from_server = self.get_response()
315                             if md5_from_server[‘status_code‘] == 258:
316                                 if md5_from_server[‘md5‘] == md5_val:
317                                     print("%s 文件一致性校验成功!" % base_filename)
318                                     with open(‘data\\breakpoint‘, ‘wb‘) as br_po:
319                                         br_po.write()
320                             print(md5_val, md5_from_server)
321
322
323
324                     else:
325                         progress = self.show_progress(response[‘file_size‘])  # generator
326                         progress.__next__()
327                         while received_size < response[‘file_size‘]:
328                             data = self.sock.recv(4096)
329                             received_size += len(data)
330                             file_obj.write(data)
331                             try:
332                                 progress.send(len(data))
333                             except StopIteration as e:
334                                 print("100%")
335                         else:
336                             print("-----file rece done-----")
337                             file_obj.close()
338                             with open(‘data\\breakpoint‘, ‘wb‘) as br_po:
339                                 br_po.write()
340             except Exception as e:
341                 base_file_size = os.path.getsize(base_filename)
342                 with open(‘data\\breakpoint‘, ‘wb‘) as br_po:
343                     data_header[‘breakpoint‘] = base_file_size
344                     br_po.write(json.dumps(data_header).encode())
345         else:print(‘There is no need to transfer files..‘)
346
347
348     def _helps(self,*args,**kwargs):
349         ‘‘‘帮助信息‘‘‘
350         helps = ‘‘‘
351             get 文件名     #下载文件
352             put 文件名     #上传文件
353             ls             #获取当前目录下的所有文件
354             cd             #改变工作目录
355             breakpoint     #断点续传‘‘‘
356         print(helps)
357
358
359     def interactive(self):
360         ‘‘‘根据命令分配函数‘‘‘
361         if self.authenticate():
362             print(‘---start interactive iwth u...(helps  帮助信息)‘)
363             while True:
364                 choice = input("[%s]:" % self.user).strip()
365                 if len(choice) == 0: continue
366                 cmd_list = choice.split()
367                 if hasattr(self, "_%s" % cmd_list[0]):
368                     func = getattr(self, "_%s" % cmd_list[0])
369                     func(cmd_list)
370                 else:
371                     print("Invalid cmd")
372
373
374
375 if __name__ == ‘__main__‘:
376     ftp = FTPClient()
377     ftp.interactive()

client端

时间: 2024-12-12 14:31:42

socketserver实现FTP的相关文章

使用 SocketServer 实现 FTP Server

使用 SocketServer 实现 FTP Server ,以便让多个客户端进行上传下载 [[email protected] ~]# cat ftp_server.py#!/usr/bin/env python#!-*- coding:utf-8 -*- import threading import SocketServer class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler): def handle(self):

python学习之路(三)使用socketserver进行ftp断点续传

最近学习python到socketserver,本着想试一下水的深浅,采用Python3.6. 目录结构如下: receive_file和file为下载或上传文件存放目录,ftp_client为ftp客户端,ftp_server为server端. server端源码: #!/usr/bin/env python # -*- coding:utf-8 -*- import socketserver import os error_code = {'400':'FILE IS NOT EXISTS'

python socketserver 实现 ftp功能

需求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ,且只能访问自己的家目录 对用户进行磁盘配额,每个用户的可用空间不同 允许用户在ftp server上随意切换目录 允许用户查看当前目录下文件 允许上传和下载文件,保证文件一致性 文件传输过程中显示进度条 附加功能:支持文件的断点续传 client: #coding:utf-8 import socket import json import os #client.connect(('192.168.16.200',9999))

python学习道路(day9note)(socketserver编程,ftp)

1.ftp client 1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 4 5 import socket 6 import subprocess 7 8 user_data = { 9 'user':None, 10 } 11 12 user_status = False #用户验证,只是当用户可以链接的时候需要去验证一下用户密码 13 def login(): 14 count = 0 15 global user_status 16 whi

Python开发程序:支持多用户在线的FTP程序

作业:开发一个支持多用户在线的FTP程序 要求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ,且只能访问自己的家目录 对用户进行磁盘配额,每个用户的可用空间不同 允许用户在ftp server上随意切换目录 允许用户查看当前目录下文件 允许上传和下载文件,保证文件一致性 文件传输过程中显示进度条 附加功能:支持文件的断点续传(仅下载) 程序 1.最最重要的readme: ### 作者介绍: * author:lzl ### 博客地址: * http://www.cnblogs.c

Python:socket实现ftp程序

刚开始学习socket编程,还不是特熟练,码了好长时间,中间遇到许多问题,记录一下用socketserver写ftp server端: 1 #!/usr/bin/env python 2 3 import socketserver,os 4 5 class FTP(socketserver.BaseRequestHandler): 6 def handle(self): 7 def clientsend(filename): 8 f = open('/ftp/%s' %filename,'w')

python day9

python 第九天  ----------------------------------------------------------------------------------------------------- socket网络编程 # 服务器端     1.IP,端口     2.监听     3.连接池     4.收,发 # 客户端     1.连接服务器端IP,端口     2.发,收 一.socket单线程   1.socket 简单使用,一次性程序 ---------

Python线程和协程-day10

写在前面 上课第10天,打卡: 感谢Egon老师细致入微的讲解,的确有学到东西! 一.线程 1.关于线程的补充 线程:就是一条流水线的执行过程,一条流水线必须属于一个车间: 那这个车间的运行过程就是一个进程: 即一个进程内,至少有一个线程: 进程是一个资源单位,真正干活的是进程里面的线程: 线程是一个执行单位: 多线程:一个车间内有多条流水线,多个流水线共享该车间的资源: 一个进程内有多个线程,多线程共享一个进程的资源: 线程创建的开销要远远小于创建进程的开销: 进程之间更多的是一种竞争关系:

socket&socket实现ftp的get方法、socketserver

首先了解socket工作原理,client-server模式 1.socket客户端: 2.socket类型 3.socket数据流 4.实验 (1)写一个client 服务端启动监听ip和端口 admindeMacBook-Air-62:~ admin$ nc -l 1234 客户端连接服务端,发数据,关闭socket pycharm中添加一个socket_client.py并之行: import socket HOST = '127.0.0.1' PORT = 1234 s = socket