def download(conn, uid, path, filename): """ 下载文件:读取已存在的文件,再进行传输 :param conn: socket 对象 :param uid: 用户 id :param path: 用户家目录 :param filename: 文件名 :return: """ path = os.path.join(path, filename) # 断点续传 file_receive_size = transferByBroken(path) conn.send(('download|%d|%s|%d' % (uid, filename, file_receive_size)).encode(CHARSET)) file_size = int(conn.recv(1024).decode(CHARSET)) if file_receive_size != file_size: config = {'file_receive_size': file_receive_size} file_write(conn, path, file_size, config) result = receive(conn).decode(CHARSET) if result == 'Success': print_color(result, PRINT_COLOR['green']) else: print_color(result, PRINT_COLOR['red'])
def operate(conn, data): """ 操作行为 :param conn: socket 连接对象 :param data: client 传输数据 :return: """ content = data.decode(CHARSET).split('|') cmd = content[0] uid = int(content[1]) login_user = user.getUserById(uid) if login_user is None: print_color('user no exist', PRINT_COLOR['red']) return False path = os.path.join(UPLOAD_PATH, login_user['work']) if cmd == 'upload': filename = content[2] file_size = int(content[3]) return user.upload(conn, path, filename, file_size, login_user) elif cmd == 'download': filename = content[2] file_size = int(content[3]) return user.download(conn, path, filename, file_size) elif cmd == 'view': return user.view(conn, path) elif cmd == 'exit': return False
def view(conn, path): """ 查看目录下所有文件 :param conn: socket 链接对象 :param path: :return: str | bool """ if os.path.isdir(path): return send_text(conn, str(os.listdir(path))[1:-1]) else: print_color('%s is not directory' % path, PRINT_COLOR['red']) return False
def run(): """ 启动 server 端服务 :return: """ print_color('waiting connect...', PRINT_COLOR['green']) for item in threadings: item.start() for item in threadings: item.join()
def view(conn, uid): """ 查看目录下所有文件 :param conn: socket 对象 :param uid: 用户 id :return: """ conn.send(('view|%d' % (uid)).encode(CHARSET)) result = receive_text(conn).split(',') for item in result: item.strip() print_color(item[1:-1], PRINT_COLOR['blue'])
def login(account, password): """ 登录 :param log_obj: 日志对象 :return: """ uid = auth(account, password) if uid is None: print_color('login fail', PRINT_COLOR['red']) else: access_logger.info('user login use id is %d ' % (uid)) return uid
def getUserById(uid): """ 通用 用户 id 获取用户信息 :param uid: 用户 id :return: dict """ path = '%s/%s' % (DATABASE['path'], DATABASE['name']) if os.path.isfile(path): accounts = json.load(open(path)) for item in accounts: if uid == item['id']: return item return None else: print_color('file [%s] no exist' % path, PRINT_COLOR['red'])
def upload(conn, path, filename, file_size, user): """ 上传文件:接收传输的文件,再进行写 :param conn: socket 对象 :param path: 用户家目录 :param filename: 文件名 :param file_size: 文件大小 :param user: 用户信息 :return: bool """ path = os.path.join(path, filename) file_receive_size = transferByBroken(path) conn.send(('%d|%d' % (file_receive_size, user['available_space'])).encode(CHARSET)) # 可用存储空间不足 if user['available_space'] < file_size - file_receive_size: print_color( 'user id [%d] not enough storage space, the available space is %s' % (user['id'], format_storage(user['available_space'])), PRINT_COLOR['red']) return False config = {'file_receive_size': file_receive_size} file_write(conn, path, file_size, config) if config['file_receive_size'] == file_size: # todo 需要更新 accounts.json 文件 user['available_space'] -= file_size user['used_space'] += file_size trans_logger.info('upload [%s] success' % path) conn.send('Success'.encode(CHARSET)) return True else: trans_logger.error('upload [%s] fail' % path) conn.send('Fail'.encode(CHARSET)) return False
def interactive(): """ 与 client 进行交互 :return: """ while True: # 阻塞连接 conn, addr = sk.accept() # 打印连接地址 print_color('connect address is %s, port is %s' % (addr[0], addr[1]), PRINT_COLOR['green']) uid = -1 while uid == -1: uid = login(conn, receive(conn)) while True: data = receive(conn) if data.decode(CHARSET) == 'exit': break if operate(conn, data) == False: print_color('operate [%s] fail' % data.decode(CHARSET), PRINT_COLOR['red']) else: print_color('operate [%s] success' % data.decode(CHARSET), PRINT_COLOR['green'])
def login(conn): """ 登录 :param conn: socket 连接对象 :return: """ retry_count = 0 uid = -1 while uid == -1 and retry_count < 3: account = input_color('please input account').strip() password = input_color('please input password').strip() conn.send(('login|%s|%s' % (account, password)).encode(CHARSET)) # 先接收信息的总长度 uid = int(conn.recv(1024).decode(CHARSET)) if uid == -1: retry_count += 1 print_color('account or password error, please try again!', PRINT_COLOR['red']) else: print_color('user login use id is [%s] ' % uid, PRINT_COLOR['green']) return uid else: print_color("account [%s] too many login attempts!" % account, PRINT_COLOR['red']) exit()
def init(conn): """ 初始化 :param conn: socket 连接对象 :return: """ print_color('please login', PRINT_COLOR['pink']) uid = login(conn) while True: operate = input_color('please input operate').strip().split('|') cmd = operate[0] if cmd in OPERATE_TYPES: if cmd == 'view': view(conn, uid) else: path = operate[1] filename = operate[2] if cmd == 'upload': upload(conn, uid, path, filename) elif cmd == 'download': download(conn, uid, path, filename) elif cmd == 'exit': conn.send(cmd.encode(CHARSET)) print_color('exit success', PRINT_COLOR['red']) exit() else: print_color('operate [%s] no exist', PRINT_COLOR['red'])
def upload(conn, uid, path, filename): """ 上传文件:接收传输的文件,再进行写 :param conn: socket 对象 :param uid: 用户 id :param path: 用户家目录 :param filename: 文件名 :return: """ path = os.path.join(path, filename) if os.path.isfile(path): file_size = os.stat(path).st_size upload_path = 'upload|%d|%s|%d' % (uid, filename, file_size) conn.send(upload_path.encode(CHARSET)) file_send_size, available_space = receive(conn).decode(CHARSET).split( '|') file_send_size = int(file_send_size) available_space = int(available_space) if available_space < file_size - file_send_size: print_color( 'you have not enough storage space, the available space is %s' % format_storage(available_space)) return False config = {'file_send_size': file_send_size} send_file(conn, path, file_size, config) result = receive(conn).decode(CHARSET) if result == 'Success': print_color(result, PRINT_COLOR['green']) else: print_color(result, PRINT_COLOR['red']) else: print_color('%s/%s file no exist' % (path, filename))
def auth_by_file(account, password): account_file = "%s/%s" % (DATABASE['path'], DATABASE['name']) if os.path.isfile(account_file): accounts = json.load(open(account_file)) md5_password = hashlib.md5() md5_password.update(password.encode(CHARSET)) password = md5_password.hexdigest() for item in accounts: if account == item['account'] and password == item['password']: print_color('auth success', PRINT_COLOR['green']) return item['id'] print_color('auth fail', PRINT_COLOR['red']) return None else: print_color( "%s/%s.json does not exist!" % (DATABASE['path'], DATABASE['name']), PRINT_COLOR['red']) return None