一、作业需求

1. 用户加密认证(已完成)

2. 多用户同时登陆(已完成)

3. 每个用户有自己的家目录且只能访问自己的家目录(已完成)

4. 对用户进行磁盘配额、不同用户配额可不同(已完成)

5. 用户可以登陆server后,可切换目录(已完成)

6. 查看当前目录下文件(已完成)

7. 上传下载文件,保证文件一致性(已完成)

8. 传输过程中现实进度条(已完成)

9. 支持断点续传(未完成)

readme:

一、作业需求:

1. 用户加密认证(已完成)

2. 多用户同时登陆(已完成)

3. 每个用户有自己的家目录且只能访问自己的家目录(已完成)

4. 对用户进行磁盘配额、不同用户配额可不同(已完成)

5. 用户可以登陆server后,可切换目录(已完成)

6. 查看当前目录下文件(已完成)

7. 上传下载文件,保证文件一致性(已完成)

8. 传输过程中现实进度条(已完成)

9. 支持断点续传(未完成)

二、博客地址:http://www.cnblogs.com/catepython/p/8616018.html

三、运行环境

操作系统:Win10

Python:3.6.2rcl

Pycharm:2017.1.14

四、功能实现

1)多用户同时登录,并做了用户不得重复登录判断(现为测试方便此调用方法已注释)

2)区分不同用户不同的文件目录

3)可在当前目录下上传/下载文件并保存

4)上传/下载文件进度显示

5)区分了用户本地/服务端文件目录

6)只能移动到自己家目录下的目录

cd /:移动到根目录下    cd ..:返回上一级目录    cd + 目录名:移动到指定目录下

7)新增pwd查看当前路径操作

8)查看当前目录下文件信息    

新增dir home:查看用户本地目录文件信息    dir server:查看用户服务端目录文件信息

9)每个用户有不同的磁盘配额

10)上传/下载文件后进行加密认证

11)新增mkdir操作:在当前目录下创建新目录文件

五、测试

1)文件名为空判断

2)用户信息判断

3)指令格式化判断

4)用户使用cd指令对其做了isdir()判断

5)用户使用mkdir指令时对其做了当前目录下已有同名目录判断

6)上传/下载到指定路径判断 

例:

1、当前在根目录下:E:.....\user_home

上传/下载文件完成后文件保存至根目录下

2、当前路径:E:.....\user_home\test\test2

上传/下载文件完成后文件保存在test2目录下

7)在当前路径下创建新目录文件

例:

1、当前在根目录下:E:.....\user_home

使用mkdir命令在根目录下创建新目录

2、当前路径:E:.....\user_home\test\test2

使用mkdir命令在E:.....\user_home\test\test2目录下创建新目录

8)上传/下载文件后进行加密认证:对本地文件与服务端文件做了mk5加密认证

9)做了多用户登录上传/下载

10)当用户配额<上传/下载文件时会做“磁盘配额不足无法上传/下载文件”提示

六、备注
1、断点续传功能有空时可以新增并完善

readme

二、流程图

三、目录结构图

四、代码区

bin目录下程序开始文件

#-*- Coding:utf-8 -*-
# Author: D.Gray
import os,sys
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR) from core import ftp_client
fc = ftp_client.Ftp_client()

start_client.py

#-*- Coding:utf-8 -*-
# Author: D.Gray
import os,sys
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR) from core import ftp_server
fs = ftp_server.Ftp_server()

start_server.py

conf目下的setting.py系统配置文件

#-*- Coding:utf-8 -*-
# Author: D.Gray
import os,sys,socket
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR) #IP和端口信息
IP_PORT = ("localhost",6969) #用户数据文件
USER_FILE = os.path.join(BASE_DIR,'db\\user_info')
#用户文件目录
USER_HOME = BASE_DIR

setting.py

core目录下主程序文件

#-*- Coding:utf-8 -*-
# Author: D.Gray
import sys,os,socket,hashlib,time,json
from conf import setting
from core import users
class Ftp_client(object):
'''
FTP客服端
'''
def __init__(self):
'''
构造函数
'''
self.client = setting.socket.socket()
self.client.connect(setting.IP_PORT)
self.help_info = """\033[33;1m
请用'put'+'空格'+'文件名'的格式下载文件
请用'get'+'空格'+'文件名'的格式上传文件
请用'cd'+'空格'+'目录名'的格式进入家目录下的子文件夹
请用'cd'+'空格'+'..'的格式返回上级目录
请用'mkdir'+'空格'+'目录名'的格式创建家目录的文件夹
输入'dir'+'空格'+'home'查看用户家目录
输入'dir'+'空格'+'server'查看用户服务端家目录
\033[0m"""
if self.auth():
self.start() def auth(self):
'''
用户登录认证函数
1、用户输入账号密码
2、序列化用户信息字典发送给服务端
3、接收服务端用户登录认证消息
4、认证成功返回True给构造函数
5、用户进入start()函数进行指令操作
:return:
'''
while True:
username = input("请输入账户名>>>:").strip()
password = input('请输入用户密码>>>:').strip()
#auth = 'auth %s %s'%(username,password)
mesg = {
"action":'auth',
"username":username,
"password":password
}
self.client.send(json.dumps(mesg).encode())
self.user_obj = users.Users(username)
back_res = self.client.recv(1024).decode()
if back_res == 'ok':
print("\033[32;1m认证成功\033[0m")
user = self.user_obj.get_user()
self.user_name = user["username"]
self.user_type = user["type"]
self.user_path = user['home']
self.disk_quota = user["disk_quota"]
self.pwd_path = os.path.join(setting.USER_HOME,self.user_path,"user_home") #定义一个默认路径
return True
elif back_res == "":
print("\033[31;1m密码错误\033[0m")
elif back_res == "":
print("\033[31;1m该用户已登录\033[0m")
else:
print("\033[31;1m用户不存在\033[0m") def start(self):
'''
用户操作函数
1、用户输入操作指令
2、判断操作指令是否有效
3、反射指令
:return:
'''
while True:
user_inport = input("%s>>>:"%(self.user_name)).strip()
if len(user_inport) == 0 :continue
user_inport = user_inport.split()
if user_inport[0] == 'q':
break
if hasattr(self,user_inport[0]):
func = getattr(self,user_inport[0])
func(user_inport)
else:
print("\033[31;1m请输入有效指令:\033[0m",self.help_info)
continue def put(self,cmd):
'''
下载服务端文件函数
1、接收服务端回调信息(305 = 服务端文件不存在或下载文件大小)
2、判断磁盘配额和文件大小
3、接收服务端回调信息
4、开始接收文件并打印进度条
5、加密认证
6、重新计算磁盘配额 调用Users类中update_disk_quota()方法将最新磁盘配额参数重新写入用户文件中
:param cmd:
:return:
'''
if len(cmd) < 2:
print("\033[31;1m请输入有效指令:\033[0m", self.help_info)
else:
'''
下载服务端文件
'''
mesg = {
"action": cmd[0],
"file_name": cmd[1],
"disk_quota": self.disk_quota
}
self.client.send(json.dumps(mesg).encode())
server_back = self.client.recv(1024).decode()
print("\033[32;1m收到服务器回调:\033[0m",server_back)
if server_back == '':
print("\033[31;1m文件不存在\033[0m")
else:
file_total_size = int(server_back)
print("\033[32;1m下载文件总大小:\033[0m", file_total_size)
print("\033[32;1m磁盘配额还剩:%sM\033[0m" % mesg["disk_quota"])
if file_total_size >= mesg["disk_quota"] * (2 ** 20):
print('\033[31;1m磁盘配额不够无法下载文件\033[0m')
else:
revered_size = 0
# file_path = os.path.join(setting.USER_HOME,self.user_path,"user_home",cmd[1])
file_path = os.path.join(self.pwd_path,cmd[1])
print('in the put_pwd_path:',file_path)
self.client.send(b"ok")
self.m = hashlib.md5()
i = 0
with open(file_path,'wb') as f:
while revered_size < file_total_size:
if file_total_size - revered_size < 1024:
size = file_total_size - revered_size
else:
size = 1024
data = self.client.recv(size)
revered_size += len(data)
'''
打印进度条
'''
str1 = "已接受 %sByte"%revered_size
str2 = '%s%s'%(round((revered_size/file_total_size)*100,2),'%')
str3 = '[%s%s]'%('*'*i,str2)
sys.stdout.write('\033[32;1m\r%s%s\033[0m'%(str1,str3))
sys.stdout.flush()
i += 2
time.sleep(0.3)
'''
加密认证
'''
self.m.update(data)
f.write(data)
self.encryption()
'''
磁盘配额
'''
new_disk_quota = round((mesg["disk_quota"] * (2 ** 20) - file_total_size) / (2 ** 20), 2)
# mesg["disk_quota"]* (2 ** 20) 将用户文件中磁盘参数转成相应的Bytes数值
self.user_obj.update_disk_quota(new_disk_quota)
print("\033[32;1m磁盘配额还剩:%sM\033[0m"%new_disk_quota) def get(self,cmd):
'''
客户端上传文件至服务端函数
1、判断指令格式是否正确
2、上传文件或文件路径是否有效和存在
3、获取文件大小
4、判断磁盘配额是否大于文件大小
5、获取服务端上传文件回调请求
6、发送文件并打印进度条
7、加密认证
8、重新计算磁盘配额 调用Users类中update_disk_quota()方法将最新磁盘配额参数重新写入用户文件中
:param cmd:
:return:
'''
if len(cmd) < 2:
print("\033[31;1m请输入有效指令:\033[0m", self.help_info)
else:
'''
上传文件
'''
file_path = os.path.join(self.pwd_path,cmd[1])
if os.path.isfile(file_path):
file_total_size = os.stat(file_path).st_size
mesg = {
"action": cmd[0],
"file_name": cmd[1],
"disk_quota": self.disk_quota,
"file_size" : file_total_size
}
print("\033[32;1m磁盘配额还剩:%sM\033[0m" % mesg["disk_quota"])
if file_total_size >= mesg["disk_quota"]*(2**20):
print("\033[31;1m磁盘配额不够无法上传文件\033[0m")
else:
self.client.send(json.dumps(mesg).encode())
print("\033[32;1m上传文件总大小:\033[0m", file_total_size)
self.client.recv(1024)
print("开始发送文件")
self.m = hashlib.md5()
send_size = 0
i = 0
with open(file_path,'rb')as f:
while send_size < file_total_size:
if file_total_size - send_size <1024:
size = file_total_size - send_size
data = f.read(size)
send_size += len(data)
else:
data = f.read(1024)
send_size += len(data)
self.client.send(data)
'''
打印进度条
'''
str1 = "已上传 %sByte:" %send_size
str2 = '%s%s' % (round((send_size / file_total_size) * 100, 2), '%')
str3 = '[%s%s]' % ('*'*i, str2)
sys.stdout.write('\033[32;1m\r%s%s\033[0m' % (str1, str3))
sys.stdout.flush()
i += 2
time.sleep(0.3)
'''
文件加密
'''
self.m.update(data)
self.encryption()
'''
磁盘配额
'''
new_disk_quota = round((mesg["disk_quota"]*(2**20) - file_total_size)/(2**20),2)
self.user_obj.update_disk_quota(new_disk_quota)
print("\033[32;1m磁盘配额还剩:%sM\033[0m"%new_disk_quota)
else:
print("\033[31;1m文件不存在\033[0m") def encryption(self):
'''
文件加密函数
1、判断用户是否需要加密
2、取消加密发送'401'信息给服务端
3、确认加密发送'400'信息给服务端
4、接收服务端文件加密信息
5、判断客户端和服务端文件加密信息是否一致
:return:
'''
encryption = input("\n文件已接收是否需要加密认证...按q取消加密>>>")
if encryption != 'q':
self.client.send(b'')
print('\033[32;1m确认加密\033[0m')
file_md5 = self.m.hexdigest()
server_back_md5 = self.client.recv(1024).decode()
print("\033[32;1m本地文件加密:%s\n服务端文件加密:%s\033[0m" % (file_md5, server_back_md5))
if file_md5 == server_back_md5:
print("\033[32;1m加密认证成功\033[0m")
else:
print("加密认证失败")
else:
self.client.send(b'')
print("\033[32;1m\n已取消加密.文件接收成功\033[0m") def dir(self,cmd):
'''
查看根目录下文件信息函数
1、dir_home 查看用户本地文件内容
2、dir_server 查看用户服务器文件内容
3、接收服务端指令文件大小
4、发送接收目录信息指令
5、接收目录信息
:param cmd:
:return:
'''
if len(cmd) < 2:
print("\033[31;1m请输入有效指令:\033[0m", self.help_info)
else:
if cmd[1] == "home" or cmd[1] == 'server':
mesg = {
"action":cmd[0],
"object":cmd[1]
}
self.client.send(json.dumps(mesg).encode())
server_back = self.client.recv(1024).decode()
print('\033[32;1m收到服务端回调指令大小:\033[0m',server_back)
self.client.send("ok".encode())
revered_size = 0
revered_data = b''
while revered_size < int(server_back):
data = self.client.recv(1024)
revered_data += data
revered_size = len(data)
print('\033[32;1m实际收到指令大小:\033[0m',revered_size)
else:
print(revered_data.decode())
else:
print("\033[31;1m请输入有效指令:\033[0m", self.help_info) def mkdir(self,cmd):
'''
添加目录文件函数
1、判断指令是否正确
2、先获取当前路径
3、判断所添加目录是否已存在
4、使用os.mkdir()函数添加新目录
5、新目录添加成功
:param cmd:
:return:
'''
if len(cmd) < 2:
print("\033[31;1m请输入有效指令:\033[0m", self.help_info)
else:
# file_path = os.path.join(setting.USER_HOME,self.user_path,"user_home",cmd[1])
file_path = os.path.join(self.pwd_path,cmd[1])
print("当前路径:", file_path)
if os.path.exists(file_path):
print("\033[31;1m该目录文件夹已存在\033[0m")
else:
os.mkdir(file_path)
print("该目录文件夹创建成功") def cd(self,cmd):
'''
CD:移动到指定目录函数
1、先判断指令是否正确
2、判断路径是否有效
3、根据输入做相应操作如:cd ..:移动到上一级目录 cd / :移动到根目录 cd 目录名:移动到指定目录
4、拆分路径重新拼接新路径
5、返回self.pwd_path当前所在目录
:param cmd:
:return:
'''
if len(cmd) < 2:
print("\033[31;1m请输入有效指令:\033[0m", self.help_info)
else:
if cmd[1] == '..':
list = []
pwd_path = os.path.join(self.pwd_path)
for index in pwd_path.split('\\'): #列表形式拆分当前目录路径以'\\'分隔
list.append(index) #将目录路径参数添加至list列表中
list[0] = '%s%s'%(list[0],'/') #将列表第一个元素 E: 字符串拼接成 E:/
if list[-1] == "user_home":
print("已在根目录下")
else:
del list[-1] #删除列表最后个元素也就是上一级目录路径
self.pwd_path = ''
for item in list: #重新拼接成新的路径
self.pwd_path = os.path.join(self.pwd_path,item)
print("当前路径:",self.pwd_path)
#print(os.listdir(self.pwd_path))
elif cmd[1] == '/':
self.pwd_path = os.path.join(setting.USER_HOME,self.user_path,"user_home")
print("已返回根目录:", self.pwd_path)
else:
pwd_path = os.path.join(self.pwd_path,cmd[1]) #移动到指定目录 cmd[1]目录名
if os.path.isdir(pwd_path):
#print(os.listdir(pwd_path))
self.pwd_path = pwd_path #返回用户当前路径
print("当前路径:", self.pwd_path)
else:
print("\033[31;1m系统找不到指定的路径\033[0m") def pwd(self,cmd):
'''
显示当前目录路径
:param cmd:
:return:
'''
print("当前路径:", self.pwd_path)
print(os.listdir(self.pwd_path)) def help(self,cmd):
'''
帮助文档函数
:param cmd:
:return:
'''
print(self.help_info)

ftp_client.py

#-*- Coding:utf-8 -*-
# Author: D.Gray
import sys,os,socket,hashlib,socketserver,json,time
from conf import setting
from core import users
class MyServer(socketserver.BaseRequestHandler):
print('等待链接...')
'''
FTP服务端类
'''
def auth(self,*args):
'''
用户登录认证函数
1、接收客户端用户字典信息
2、序列化字典信息
3、调用Users类中get_user()函数
4、判断用户是否有效
5、发送认证信息至客户端
:param args:
:return:
'''
cmd = args[0]
self.user_obj = users.Users(cmd['username'])
auth_user = self.user_obj.get_user()
if auth_user:
if auth_user['password'] == cmd["password"]:
if auth_user['status'] == 0:
self.request.send(b"ok")
#self.user_obj.update_status_close()
self.user_home = auth_user["home"]
self.user_type = auth_user["type"]
else:
self.request.send(b"")
print("\033[31;1m该用户已登录\033[0m")
else:
self.request.send(b'')
print("\033[31;1m密码错误\033[0m")
else:
self.request.send(b"")
print("\033[31;1m用户名不存在\033[0m") def put(self,*args):
'''
服务端发送文件给客户端
1、判断文件是否存在
2、获取文件总大小
3、发送文件大小给客户端
4、接收客户端下载文件请求
5、开始循环发送文件给客户端
6、发送完成后调用加密函数
:param args:
:return:
'''
cmd = args[0]
file_path = os.path.join(setting.USER_HOME,self.user_home,'server_home',cmd["file_name"])
if os.path.isfile(file_path):
file_total_size = os.stat(file_path).st_size
print("\033[32;1m获取文件大小:\033[0m",file_total_size)
self.request.send(str(file_total_size).encode())
self.request.recv(1024)
print("开始发送文件")
self.m = hashlib.md5()
with open(file_path,'rb') as f:
for line in f:
self.m.update(line)
self.request.send(line)
self.encryption()
else:
self.request.send(b'')
print("文件不存在") def get(self,*args):
'''
服务端接收客户端发送文件函数
1、接收客户端发送文件大小
2、发送接收客户端文件请求
3、开始接收文件
4、跟踪文件接收并写入相应目录
5、接收完成后调用加密函数
:param args:
:return:
'''
cmd = args[0]
#print(cmd)
file_path = os.path.join(setting.USER_HOME,self.user_home,"server_home",cmd["file_name"])
print("\033[32;1m收到客户端发送文件大小:\033[0m", cmd["file_size"])
self.request.send(b"ok")
print("开始接收文件")
file_total_size = cmd["file_size"]
rever_size = 0
self.m = hashlib.md5()
with open(file_path,'wb') as f:
while rever_size < file_total_size:
if file_total_size - rever_size <1024:
size = file_total_size - rever_size
else:
size = 1024
data = self.request.recv(size)
rever_size += len(data)
self.m.update(data)
f.write(data)
self.encryption() def encryption(self):
'''
加密认证函数
1、发送确认加密'400'请求
2、发送服务端文件加密信息至客户端
:return:
'''
client_back = self.request.recv(1024).decode()
if client_back == "":
print("\033[32;1m确认加密请求\033[0m")
server_file_md5 = self.m.hexdigest()
self.request.send(server_file_md5.encode())
print("\033[32;1m服务端文件加密:\033[0m", server_file_md5)
else:
print("\033[32;1m\n已取消加密.客户端文件接收完成\033[0m") def dir(self,*args):
'''
服务端查看目录文件信息函数
1、序列化客户端字典信息
2、popen()获取目录文件信息
3、判断目录信息长度
4、发送目录长度信息至客户端
5、接收客户端回调请求
6、发送目录信息至客户端
:param args:
:return:
'''
cmd = args[0]
if cmd["object"] == 'home':
file_name = 'user_home'
else:
file_name = 'server_home'
file_path = os.path.join(setting.USER_HOME,self.user_home,file_name)
res = os.popen("%s %s"%(cmd["action"],file_path)).read()
print("in the dir:",res)
if len(res) == 0:
res = "has not output"
self.request.send(str(len(res.encode())).encode())
self.request.recv(1024)
self.request.send(res.encode()) def handle(self):
'''
与客户端交互函数(解析客户端操作指令)
1、接收客户端链接信息
2、接收客户端操作指令(action)需序列化
3、反射操作指令
:return:
'''
while True:
try:
self.data = self.request.recv(1024).strip()
print("{}已链接".format(self.client_address))
actin_dict = json.loads(self.data.decode())
#print(actin_dict)
print('in the handle',actin_dict["action"])
if hasattr(self,str(actin_dict["action"])):
func = getattr(self,str(actin_dict["action"]))
func(actin_dict)
except ConnectionResetError as e:
print("%s客户端已断开%s"%(self.client_address,e))
#self.user_obj.update_status_open()
break server = socketserver.ThreadingTCPServer((setting.IP_PORT),MyServer) #支持多用户操作:ThreadingTCPServer
server.serve_forever()

ftp_server.py

#-*- Coding:utf-8 -*-
# Author: D.Gray
import os,sys,json
from conf import setting
class Users(object):
'''
用户类
'''
def __init__(self,username):
self.username = username
self.user_file = setting.USER_FILE + "\\%s.json"%(self.username)
#print(self.user_file)
self.users_read = self.read_users() def read_users(self):
'''
读取用户文件信息函数
1、判断用户文件是否存在(用户是否存在)
2、遍历用户json文件中内容
3、返回遍历内容
:return:
'''
if os.path.exists(self.user_file):
with open(self.user_file, 'r') as f:
user_read = eval(f.read())
return user_read def get_user(self):
'''
1、判断服务端传过来的用户名参数是否与文件中用户名参数
2、异常处理:用户名与用户文件参数类型不一直
:return:
'''
#print('in the User_get_user:',user)
try:
if self.users_read["username"] == self.username:
return self.users_read
except TypeError as e:
pass def update_status_close(self):
'''
修改用户登录状态函数
0-未登录
1-已登录
无法重复登录
:return:
'''
with open(self.user_file,'r') as f:
fr = f.read()
fd = eval(fr) with open(self.user_file,'w') as fw:
res = fr.replace(str(fd['status']),str(1))
fw.write(res) def update_status_open(self):
'''
修改用户登录状态函数
0-未登录
1-已登录
无法重复登录
:return:
'''
with open(self.user_file, 'r') as f:
fr = f.read()
fd = eval(fr) with open(self.user_file, 'w') as fw:
res = fr.replace(str(fd['status']), str(0))
fw.write(res) def update_disk_quota(self,new_disk_quota):
'''
更改用户磁盘配额函数
:param new_disk_quota:接收客户端新磁盘配额参数
:return:
'''
with open(self.user_file,'r') as f:
fr = f.read()
fd = eval(fr) with open(self.user_file,'w') as fw:
res = fr.replace(str(fd["disk_quota"]),str(new_disk_quota))
fw.write(res)

user

db/user_info目录下的数据文件

{
"username":"alex",
"password":"admin",
"status":0,
"type":0,
"home":"home\\alex",
"disk_quota":0.97
}

alex.json

老男孩Day9作业:高级FTP的更多相关文章

  1. python作业高级FTP

    转载自:https://www.cnblogs.com/sean-yao/p/7882638.html 作业需求: 1. 用户加密认证 2. 多用户同时登陆 3. 每个用户有自己的家目录且只能访问自己 ...

  2. python作业高级FTP(第八周)

    作业需求: 1. 用户加密认证 2. 多用户同时登陆 3. 每个用户有自己的家目录且只能访问自己的家目录 4. 对用户进行磁盘配额.不同用户配额可不同 5. 用户可以登陆server后,可切换目录 6 ...

  3. 老男孩Day8作业:FTP

    1.作业需求 开发简单的FTP: 1. 用户登陆 2. 上传/下载文件 3. 不同用户家目录不同 4. 查看当前目录下文件 5. 充分使用面向对象知识 2.流程图 3.目录结构 4.代码区 bin目录 ...

  4. Python09作业思路及源码:高级FTP服务器开发(仅供参考)

    高级FTP服务器开发 一,作业要求 高级FTP服务器开发 用户加密认证(完成) 多用户同时登陆(完成) 每个用户有不同家目录且只能访问自己的家目录(完成) 对用户进行磁盘配额,不同用户配额可不同(完成 ...

  5. python第四十八天--高级FTP

    高级FTP服务器1. 用户加密认证2. 多用户同时登陆3. 每个用户有自己的家目录且只能访问自己的家目录4. 对用户进行磁盘配额.不同用户配额可不同5. 用户可以登陆server后,可切换目录6. 查 ...

  6. (转)python高级FTP

    原文地址:http://www.itnose.net/detail/6754889.html高级FTP服务器1. 用户加密认证2. 多用户同时登陆3. 每个用户有自己的家目录且只能访问自己的家目录4. ...

  7. 老男孩python作业7-开发一个支持多用户在线的FTP程序

    作业6:开发一个支持多用户在线的FTP程序 要求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ,且只能访问自己的家目录 对用户进行磁盘配额,每个用户的可用空间不同 允许用户在ftp s ...

  8. Day9作业:socket之FTP工具

    代码传的太累,直接发个github的链接吧! https://github.com/ccorzorz/Socketserver_FTP 上两张图给抛砖引玉下吧: 后台管理: FTP程序,包括客户端和s ...

  9. python第四十一天---作业:简单FTP

      作业要示: 开发简单的FTP:1. 用户登陆2. 上传/下载文件3. 不同用户家目录不同4. 查看当前目录下文件5. 充分使用面向对象知识 REDMAE 用户登陆 1.查看用户目录文件 2.上传文 ...

随机推荐

  1. Android 4 学习(15):持久化:Files, Saving State and Preferences

    参考<Professional Android 4 Development> 持久化:Files, Saving State and Preferences Android中的数据持久化 ...

  2. 关于Bootstrap的整理和理解

    随着CSS3和HTML5的流行,我们的WEB页面不仅需要更人性化的设计理念,而且需要更酷的页面特效和用户体验.作为开发者,我们需要了解一些宝贵的CSS UI开源框架资源,它们可以帮助我们更快更好地实现 ...

  3. 小白之js原生轮播图

    html: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...

  4. c# 通过dllimport 调用c 动态链接库

    https://blog.csdn.net/zhunju0089/article/details/80906501 这篇文件很详细 讲述了如何创建c 动态链接库项目 有一些注意的地方 不做介绍 下面是 ...

  5. 详解PHP执行定时任务的实现思路

    PHP本身是没有定时功能的,PHP也不能多线程.PHP的定时任务功能必须通过和其他工具结合才能实现,例如WordPress内置了wp-cron的功能,很厉害. 一.Linux服务器上使用CronTab ...

  6. POJ1308

    1.题目链接地址 http://poj.org/problem?id=1308 2.源代码 #include<iostream> using namespace std; #define ...

  7. PHP网站

    1.NetBeans 解决PHP调试问题:https://netbeans.org/ 支持PHP调试的版本 2. http://document.thinkphp.cn/manual_3_2.html ...

  8. java用JDBC连接数据库的方式

    //驱动位置String sDBDriver = "com.microsoft.sqlserver.jdbc.SQLServerDriver";//连接数据库地址名字String ...

  9. php析构方法关于栈的问题

    <?php class test{ var $name; var $sex; var $age; function __construct( $name, $sex ,$age ) { $thi ...

  10. file_get_content() 超时

    set_time_limit 只能影响php 程序的超时时间. file_get_contents 读取的是URL的超时时间.   因此 set_limit_limit 对file_get_conte ...