开发简单的FTP:

1. 用户登陆

2. 上传/下载文件

3. 不同用户家目录不同

4. 查看当前目录下文件

5. 充分使用面向对象知识

1、目录结构
zuoye-ftp
├── chenliang #用户chenliang的FTP根目录
├── download #所有用户下载的时候默认文件路径
├── lw #用户lw的FTP根目录
├── lzd #用户lzd的FTP根目录
├── wangjun #用户wangjun的FTP根目录
├── wdl #用户wdl的FTP根目录
├── xueli #用户xueli的FTP根目录
├── create-users.py #创建用户专用py文件
├── ros.zip #模拟上下载的测试文件ros.zip
├── socket_client.py #客户端文件
├── socket_server.py #服务端文件
├── user_data.bak #shelve文件
├── user_data.dat #shelve文件
└── user_data.dir #shelve文件

2、创建用户运行create-users.py,默认帐号密码是一致的。已有用户chenliang,lw,lzd,wangjun,wdl,xueli
3、创建的用户,在执行服务端的时候,自动会生成一个自己用户的FTP根目录,同时便于测试会复制ROS.zip到自己根目录
4、先运行socket_server.py,默认socket的服务端端口号为6969
5、再运行socket_client.py

create-users.py

#!/usr/bin/env python
#-*-coding:utf-8-*-
#Author:lzd
#创建用户名和密码,默认用户名和密码一致
import shelve
userlist=[]
user_data=shelve.open("user_data")
# for i in user_data.items():
# print(i)
print("当前已有的所有用户的用户名如下:")
for i in user_data.keys():
userlist.append(user_data[i])
print(userlist)
while True:
username=input("请输入用户名\n")
if username in userlist:
print("用户名重复啦,请重新输入用户名!")
continue
else:
password=input("请输入用户密码\n")
break
user_data[username]=password
user_data.close()
print("用户创建成功~!")

socket_server.py

#!/usr/bin/env python
#-*-coding:utf-8-*-
#Author:lzd
#服务器端
import os
gongzuopath=os.getcwd()
# print(gongzuopath)
import time
#print(time.strftime("%Y%m%d%H%M%S",time.localtime()))
import socket
server = socket.socket()
server.bind(('localhost',6969)) #绑定要监听端口
server.listen() #监听
import shutil
import shelve
userlist=[]
user_data=shelve.open("user_data")
for i in user_data.keys():
userlist.append(user_data[i])
if not os.path.exists(gongzuopath+r"/"+i):
os.mkdir(gongzuopath+r"/"+i)
if not os.path.exists(gongzuopath+r"/"+i+"/ros.zip"):
shutil.copyfile(gongzuopath+r"/ros.zip",gongzuopath+r"/"+i+"/ros.zip")
print("我要开始等电话了")
while True:
Flag = True
conn, addr = server.accept() # 等电话打进来
# conn就是客户端连过来而在服务器端为其生成的一个连接实例
print(conn, addr)
print("电话来了")
while Flag:
data = conn.recv(1024)
print("recv:",data)
if not data:
print("client has lost...")
break
clientuser=data.decode("utf-8")
if clientuser in userlist:
conn.send("请输入用户密码".encode("utf-8"))
data = conn.recv(1024)
print("recv:",data)
if not data:
print("client has lost...")
break
if data.decode("utf-8")==user_data[clientuser]:
conn.send("用户名密码验证成功".encode("utf-8"))
while Flag:
data = conn.recv(1024)
print("recv:", data)
if data=="choose3".encode("utf-8"):
if ",".join(os.listdir(gongzuopath+r"/"+clientuser)).encode("utf-8"):
conn.send(",".join(os.listdir(gongzuopath+r"/"+clientuser)).encode("utf-8"))
else:
conn.send("当前目录下为空".encode("utf-8"))
elif data=="choose1".encode("utf-8"):
conn.send("服务端准备接收文件".encode())
data = conn.recv(1024).decode("utf-8") #收到文件大小,单位byte
filesize=data
print("recv:文件大小为", data)
tmpdata="服务端准备接收大小为"+data+"的文件"
conn.send(tmpdata.encode())
serverfile=gongzuopath+r"/"+clientuser+"/"+time.strftime("%Y%m%d%H%M%S",time.localtime())
f = open(serverfile, "wb")
while str(os.stat(serverfile).st_size) != filesize:
data=conn.recv(10240000)
f.write(data)
f.flush()
else:
conn.send("文件发送完毕".encode("utf-8"))
elif data=="choose2".encode("utf-8"):
if ",".join(os.listdir(gongzuopath + r"/" + clientuser)).encode("utf-8"):
conn.send(",".join(os.listdir(gongzuopath + r"/" + clientuser)).encode("utf-8"))
else:
conn.send("当前目录下为空".encode("utf-8"))
continue
data = conn.recv(1024).decode("utf-8")
print(data)
if not data:
continue
print("recv:客户端要下载的文件名", data)
fpath=gongzuopath+r"/"+clientuser+r"/"+data
fpath_size = str(os.stat(fpath).st_size)
f = open(fpath, "rb")
filedata = f.read()
conn.send(fpath_size.encode("utf-8"))
conn.sendall(filedata)
data = conn.recv(1024)
print(data.decode("utf-8")) # 文件接收完毕
elif data=="choose4".encode("utf-8"):
Flag=False
else:
conn.send("用户名密码验证失败".encode("utf-8"))
else:
conn.send("输入的用户名不存在".encode()) server.close()

socket_client.py

#!/usr/bin/env python
#-*-coding:utf-8-*-
#Author:lzd
#客户端
import socket
import os
gongzuopath=os.getcwd()
# print(os.stat(gongzuopath+"/lzd/"+"ros.zip").st_size)
client = socket.socket() #声明socket类型,同时生成socket连接对象
client.connect(('localhost',6969))
while True:
username=input("请输入用户名\n")
if len(username) == 0: continue
client.send(username.encode("utf-8"))
data=client.recv(1024)
print(data.decode())
if data.decode()=="请输入用户密码":
password=input("")
client.send(password.encode("utf-8"))
data=client.recv(1024)
print(data.decode())
if data.decode()=="用户名密码验证失败":
continue
elif data.decode()=="用户名密码验证成功":
while True:
print("%s当前的工作目录为/%s"%(username,username))
print("""
1、上传文件;
2、下载文件;
3、查看当前目录下的所有文件;
4、退出程序
请输入你想操作的数字?
""")
choose=input("")
if choose=="":
print("当前用户的工作目录下所有文件如下:")
print(",".join(os.listdir(gongzuopath + r"/" + username)))
fpath2=input("请输入你想上传到服务器的文件名,为便于测试,当前目录下有个1M的文件ros.zip\n")
print("默认会在当前用户的目录下生成一个当前时间的文件。")
if not fpath2:
continue
fpath=gongzuopath+r"/"+username+r"/"+fpath2
fpath_size=str(os.stat(fpath).st_size)
f=open(fpath,"rb")
filedata=f.read()
client.send("choose1".encode("utf-8"))
data = client.recv(1024)
print(data.decode("utf-8")) #服务器准备接收文件
client.send(fpath_size.encode("utf-8"))
data = client.recv(1024)
print(data.decode("utf-8")) #服务端准备接收大小为%s的文件
client.sendall(filedata)
data = client.recv(1024)
print(data.decode("utf-8")) # 文件发送完毕
if choose=="":
client.send("choose2".encode("utf-8"))
data = client.recv(1024)
print("您当前的工作目录下,所有的文件如下:")
print(data.decode("utf-8")) # 显示当前工作目录下所有文件
if data.decode("utf-8")=="当前目录下为空":
continue
print("您想下载哪个文件到本地?默认下载到当前脚本的工作目录的download目录")
fpath2 = input("请输入你想下载的文件名\n")
client.send(fpath2.encode("utf-8"))
fpath = gongzuopath + r"/download/" + fpath2
data = client.recv(1024).decode("utf-8")
file_size=data
print("您想下载的文件大小为:",data)
f = open(fpath, "wb")
while str(os.stat(fpath).st_size) != file_size:
data = client.recv(10240000)
f.write(data)
f.flush()
else:
client.send("文件接收完毕".encode("utf-8"))
print("文件接收完毕")
if choose=="":
client.send("choose3".encode("utf-8"))
data = client.recv(1024)
print("您当前的工作目录下,所有的文件如下:")
print(data.decode("utf-8"))
if choose=="":
client.send("choose4".encode("utf-8"))
client.close()
exit()

第七周作业——简单FTP的更多相关文章

  1. 2017-2018-1 我爱学Java 第六七周 作业

    团队六七周作业 完善版需求规格说明书 制定团队编码规范 数据库设计 后端架构设计 TODOList 参考资料 完善版需求规格说明书 <需求规格说明书>初稿不足之处: 1.开发工具写错 2. ...

  2. 2018-2019-1 20189221 《Linux内核原理与分析》第七周作业

    2018-2019-1 20189221 <Linux内核原理与分析>第七周作业 实验六 分析Linux内核创建一个新进程的过程 代码分析 task_struct: struct task ...

  3. 2017-2018-1 JAVA实验站 第六、七周作业

    2017-2018-1 JAVA实验站 第六.七周作业 详情请见团队博客

  4. 2017-2018-1 JaWorld 第六、七周作业

    2017-2018-1 JaWorld 第六.七周作业 修改需求规格说明书 上次的<需求规格说明书>初稿有哪些不足? 王译潇同学回答:   1. 引言和目的性考虑的不是很周全.   2. ...

  5. 2017-2018-1 20179205《Linux内核原理与设计》第七周作业

    <Linux内核原理与设计>第七周作业 视频学习及操作分析 创建一个新进程在内核中的执行过程 fork.vfork和clone三个系统调用都可以创建一个新进程,而且都是通过调用do_for ...

  6. 2019-2020-1 20199325《Linux内核原理与分析》第七周作业

    第七周作业 1.进程描述符task_struct数据结构(一) 为了管理进程,内核必须对每个进程进行清晰的描述,进程描述符提供了内核所需了解的进程信息. struct task_struct数据结构很 ...

  7. 2019-2020-1 20199329《Linux内核原理与分析》第七周作业

    <Linux内核原理与分析>第七周作业 一.本周内容概述: 对Linux系统如何创建一个新进程进行追踪 分析Linux内核创建一个新进程的过程 二.本周学习内容: 1.学习进程的描述 操作 ...

  8. 2020-2021-1 20209307《Linux内核原理与分析》第七周作业

    这个作业属于哪个课程 <2020-2021-1Linux内核原理与分析)> 这个作业要求在哪里 <2020-2021-1Linux内核原理与分析第七周作业> 这个作业的目标 & ...

  9. 1903021116—吉琛—Java第七周作业—客户类测试

    项目 内容 课程班级博客链接 19信计班 这个作业要求链接 第七周作业链接 博客名称 学号-姓名-Java第七周作业-客户类测试 要求 每道题要有题目,代码(使用插入代码,不会插入代码的自己查资料解决 ...

随机推荐

  1. Django中关于事务的代码编写

    Django中对于数据库的事务,默认每执行一句数据库操作,便会自动提交. 在Django中可以通过django.db.transaction模块提供的atomic来定义一个事务,atomic提供两种用 ...

  2. js 要写严格模式

    js 为了能在移动端通用,要写严格模式: 这里多了个逗号,在pc上浏览器可以通过,但是在手机端就不能.

  3. Anaconda使用、conda的环境管理和包管理

    关于Anaconda的安装参考本人之前的博文 http://www.cnblogs.com/bymo/p/8034661.html 关于Anaconda的概述和详细使用参考:https://www.j ...

  4. java android 读写西门子PLC数据,包含S7协议和Fetch/Write协议,s7支持200smart,300PLC,1200PLC,1500PLC

    本文将使用一个gitHub开源的组件技术来读写西门子plc数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能读写操作 gi ...

  5. 音乐随想——斯美塔那—G小调钢琴协奏曲

    乐源 Music -> Piano Trio -> Smetana:Piano Trioin G minor Op.15 总结 每一乐章都会有一段美到极致的主旋律. 第一乐章 起头即有凄凉 ...

  6. rancher下的kubernetes之一:构建标准化vmware镜像

    学习kubernetes的时候,我们需要在kubernetes环境下实战操作,然而kubernetes环境安装并不容易,现在通过rancher可以简化安装过程,咱们来实战rancher下的kubern ...

  7. 让控制台支持 ANSI 转义序列,输出下划线、修改颜色或其他控制

    各种操作系统的控制台都支持 ANSI 转义序列(ANSI Escape Code).使用转义序列,可以对控制台进行很多额外的定制,例如修改颜色.修改标题栏,将文字添加下划线等. 当然,.NET 已经帮 ...

  8. 应该抛出什么异常?不应该抛出什么异常?(.NET/C#)

    我在 .NET/C# 建议的异常处理原则 中描述了如何 catch 异常以及重新 throw.然而何时应该 throw 异常,以及应该 throw 什么异常呢? 究竟是谁错了? 代码中从上到下从里到外 ...

  9. WPF 程序无法触摸操作?我们一起来找原因和解决方法!

    WPF 自诞生以来就带着微软先生的傲慢.微软说 WPF 支持触摸,于是 WPF 就真的支持触摸了.对,我说的是"支持触摸",那种摸上去能点能动的:偶尔还能带点儿多指的炫酷效果.但是 ...

  10. Oracle基础查询

    select * from teacher--女性老师编号.姓名select tno,tname,gendar from teacher where gendar='女'--姓韩的女性老师编号.姓名. ...