今天补充完善了用户验证功能,和上传文件的部分功能,目前还存在断点续传进行完善,这里需要复习configpraser模块的知识,还有os模块部分知识记得还是不牢,主要用的那几个还是想不起来,然后就是这些。
今天主要增加的功能:
1.用户登录验证,将用户验证路径进行修改,每次验证直接指向configpraser模块生成的文件中
2.用户完成登录后,利用实例化self.user = user 获取用户权限
3.完成部分上传功能,主要是文件已经存在的情况和文件不存在的情况,对文件存在,但文件不完整的情况下继续进行上传功能的实现未完成
4.文件路径拼接很重要
5.增加home文件夹用于存放用户的个人资料
6.增加了信息对照表,减少信息传递过程中不断重复传输的内容,通过字典进行查找,就是这前网页打不开老是蹦出“404”的原因
首先是今天修改后的文件目录情况:
客户端代码更新:
import socket import optparse import configparser import json import os STATUS_CODE = { 250 : "Invalid cmd format, e.g: {'action':'get','filename':'test.py','size':344}", 251 : "Invalid cmd ", 252 : "Invalid auth data", 253 : "Wrong username or password", 254 : "Passed authentication", 255 : "Filename doesn't provided", 256 : "File doesn't exist on server", 257 : "ready to send file", 258 : "md5 verification", 800 : "the file exist,but not enough ,is continue? ", 801 : "the file exist !", 802 : " ready to receive datas", 900 : "md5 valdate success" } # tcp_client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # tcp_client.connect(('127.0.0.1',8080)) # tcp_client.send('ok'.encode('utf-8')) # 以上是easy模式下的 class ClientHandler(): def __init__(self): self.op = optparse.OptionParser() self.op.add_option('-s','--server', dest = 'server') self.op.add_option('-P', '--port', dest='port') self.op.add_option('-u', '--username', dest='username') self.op.add_option('-p', '--password', dest='password') self.options,self.args = self.op.parse_args() self.verify_args(self.options,self.args) self.make_connection() self.mainPath = os.path.dirname(os.path.abspath(__file__)) def verify_args(self,options , args ): # 对port端口进行校验 server = options.server port = options.port # username = options.username # password = options.password if int(port) < 0 and int(port) > 65535: return True else: exit('the port is in 0~65535') def make_connection(self): self.sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) self.sock.connect(self.options.server,int(self.options.port)) def interractive(self): if self.authenticate(): print('==========begin to interactive==========') cmd_info = input('[%s]'%self.user).strip() #比如会输入 put 12.png images cmd_list = cmd_info.split('') if hasattr(self.cmd_list[0]): func = getattr(self,cmd_list[0]) func(*cmd_list) def put(self, *cmd_list): # 传入命令: put 12.png images action, local_path, target_path = cmd_list local_path = os.path.join(self.mainPath , local_path) file_name = os.path.basename(local_path) file_size = os.stat(local_path).st_size data = { 'action' : 'put', 'file_name' : file_name, 'file_size' : file_size, 'target_path' : target_path } self.sock.sendall(json.dumps(data).encode('utf-8')) is_exist = self.sock.recv(1024).decode('utf-8') # 下面对接收到的信息进行处理(转入服务端的书写) has_sent = 0 if is_exist == '800': # 表示文件存在不完整,即断点续传问题 pass elif is_exist == '801': # 表示文件已经存在,不用上传,所以就跳出put方法,重新转入输入命令那一行 # 即 interractive 方法 print("the file exist") return else: pass # 下面表示文件不存在的情况,就直接开始上传了 f = open(local_path, "rb") while has_sent < file_size: data = f.read(1024) self.sock.sendall(data) has_sent += len(data) self.show_progress(has_sent, file_size) f.close() print("put success!") def authenticate(self): if self.options.username is None or self.options.password is None: username = input('username>>>') password = input('password>>>') return get_auth_result(username,password) else: return get_auth_reult(self.options.username,self.options.password) def response(self): data = self.sock.recv(1024).decode('utf-8') data = json.loads(data) return data def get_auth_result(self,user ,pwd): data = { 'action' : 'auth', 'username' : user, 'password' : pwd } self.sock.send(json.dumps(data).encode('utf-8')) response = self.response() print('response是',response['status_code']) if response['status_code'] == 254: self.user = user print(STATUS_CODE[254]) return True else: print(STATUS_CODE['status_code']) ch = ClientHandler() ch.interractive()
settings文件信息更新:
import os BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) IP = '127.0.0.1' PORT = 8080 ACCOUNT_PATH = os.path.join(BASE_DIR , 'conf', 'account.cfg') #指向客户端密码信息的路径
服务端server.py文件更新:
import socketserver import json import configparser from conf import settings import os STATUS_CODE = { 250 : "Invalid cmd format, e.g: {'action':'get','filename':'test.py','size':344}", 251 : "Invalid cmd ", 252 : "Invalid auth data", 253 : "Wrong username or password", 254 : "Passed authentication", 255 : "Filename doesn't provided", 256 : "File doesn't exist on server", 257 : "ready to send file", 258 : "md5 verification", 800 : "the file exist,but not enough ,is continue? ", 801 : "the file exist !", 802 : " ready to receive datas", 900 : "md5 valdate success" } class ServerHandler(socketserver.BaseRequestHandler): def handle(self): while True: data = self.request.recv(1024).strip() data = json.loads(data.decode('utf-8')) ''' {'action' : 'auth' , 'username' : 'xiao', 'password' : 123 } ''' if data.get('action'): if hasattr(self,data.get('action')): func = getattr(self,data.get('action')) func(**data) else: print('func error') self.request.send('func error'.encode('utf-8')) else: print('Invalid cmd') self.request.send('Invalid cmd'.encode('utf-8')) def send_reponse(self , state_code): response = {'status_code':state_code} self.request.sendall(json.dumps(response).encode('utf-8')) def auth(self,**data): username = data['username'] password = data['password'] user = self.authenticate(username,password) if user: self.send_reponse(254) else: self.send_reponse(253) def authenticate(self,user,pwd): cfg = configparser.ConfigParser() cfg.read(settings.ACCOUNT_PATH) if user in cfg.sections(): if cfg[user]['password'] == pwd: self.user = user # 登录成功之后保存了用户的登录信息 self.mainPath = os.path.join(settings.BASE_DIR,'home',self.user) # print('passed authentication') # 表示登录成功 return user def put(self,**data): print('data',data) file_name = data.get('file_name') file_size = data.get('file_size') target_path = data.get('target_path') abs_path = os.path.join(self.mainPath,target_path,file_name) # 以上部分即已获得了想要保存文件在服务端的位置信息,可用于后续文件的打开 has_received = 0 if os.path.exists(abs_path): # 用于判断文件是否已经存在 file_has_size = os.stat(abs_path).st_size if file_has_size < file_size: # 出现了断点续传的情况 self.request.sendall('800'.encode('utf-8')) pass # 继续完善部分 else: # 表示文件已存在,且比较完整,返回给客户端801的信息 self.request.sendall('801'.encode('utf-8')) return else: self.request.sendall('802'.encode('utf-8')) f = open(abs_path , 'wb') while has_received < file_size: data = self.request.recv(1024) f.write(data) has_received += len(data) f.close()
明天将继续晚上断点续传功能、cd、dir等相关操作功能
记得看configpraser模块。