python--FTP的实现(用socket)
1、要求
作业:开发一个支持多用户在线的FTP程序
要求:
用户加密认证
允许同时多用户登录
每个用户有自己的家目录 ,且只能访问自己的家目录
对用户进行磁盘配额,每个用户的可用空间不同
允许用户在ftp server上随意切换目录
允许用户查看当前目录下文件
允许上传和下载文件,保证文件一致性
文件传输过程中显示进度条
附加功能:支持文件的断点续传
2、目录结构
userinfo里放的是ftp的用户名和密码
homedir是用来放各个用户的家目录,下面的子文件就是对应用户的家目录
代码放在code里,一个client,一个server,那个文件1是测试上传下载时用的测试文件
3、思路
(1)对于用户加密认证
就是读取userinfo中的用户名和密码,对比用户输入的信息,对的上,就可以继续其他操作,否则就不行
(2)client和server的交互
用socket实现
在client端,先建立socket对象,再connect,再send客户的信息,等待server回复,即client.recv
在server端,先建立socket对象,再bind主机和端口,设置listen,等待相应的client地址发来消息,accept它,并做出相应的反应,发回去
(3)目录的切换
用到os模块中的os.path.dirname os.getcwd os.path.join os.chdir等方法来获取当前路径、父目录、组合路径、变更路径
(4)具体代码
client如下:
1 import socket 2 import os 3 4 fddir=os.path.dirname(os.path.dirname(__file__))#project根目录 5 6 #建立socket,连接本地21端口 7 client=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 8 client.connect(('127.0.0.1',21)) 9 10 #登录验证 11 name=input("ftp登录用户名:") 12 password=input("登陆密码:") 13 loginstring='loginstring '+name+' '+password 14 client.send(loginstring.encode('utf-8')) 15 reply=client.recv(1024).decode('utf-8') 16 print(reply) 17 18 #登录成功才能有连续的ftp请求输入 19 def showdir(): 20 msg='currentdir' 21 return msg 22 def showfiles(): 23 msg='currentfiles' 24 return msg 25 def downdir(): 26 msg='downdir ' 27 msg += input('请输入你要进入的目录名字:') 28 return msg 29 def updir(): 30 msg='updir' 31 return msg 32 def download(): 33 msg = 'download ' 34 filename=input('输入你要下载的文件名(保存到当前路径)') 35 msg +=filename 36 return msg 37 def upload(): 38 msg='upload ' 39 filedir=input("输入你要上传的文件路径") 40 filename=filedir.split('\\')[-1] 41 msg += filename+' ' 42 with open(filedir,'r') as fd: 43 msg +=fd.read() 44 return msg 45 def bye(): 46 msg='exit' 47 return msg 48 49 ftprequest={'1':showdir,'2':showfiles,'3':downdir,'4':updir,'5':download,'6':upload,'7':bye} 50 if reply=='login success...': 51 ftphome = '%s\homedir\%s'%(fddir,name) 52 while True: 53 incmd = input("你要干嘛?\n" 54 "1、显示当前路径\n2、显示当前文件列表\n3、进入文件夹\n4、返回上一层\n" 55 "5、下载文件\n6、上传文件\n7、退出") 56 if incmd in ftprequest.keys(): 57 mess=ftprequest[incmd]() 58 client.send(mess.encode('utf-8')) 59 if incmd=='7': 60 break 61 reply=client.recv(102400).decode('utf-8') 62 if incmd=='5': 63 filename=input("请输入要保存的名字:") 64 filepath=os.path.join(os.getcwd(),filename) 65 with open(filepath,'w') as fd: 66 fd.write(reply) 67 print(reply) 68 client.close()
server端:
1 import socket 2 import os 3 4 #从文件获取用户名密码,放在字典里 5 userinfo={} 6 fddir=os.path.dirname(os.path.dirname(__file__))#project根目录 7 homedir=fddir+'\homedir' 8 9 with open(r'%s\userinfo\userinfo'%fddir,'r',encoding='utf-8') as userfd: 10 line=userfd.readline() 11 while line: 12 name=line.split()[0] 13 passwd=line.split()[1] 14 userinfo[name]=passwd 15 line=userfd.readline() 16 #建立服务器socket、绑定、监听 17 server=socket.socket() 18 server.bind(('127.0.0.1',21)) 19 server.listen(5) 20 #等待接收数据 21 while True: 22 print("server waiting...") 23 conn,addr=server.accept() 24 25 while True: 26 clientdata=conn.recv(1024) #1M data 27 clientdatastr=clientdata.decode('utf-8') 28 ''' 29 分辨传进来的是什么命令做相应的处理 30 1、登录命令以loginstring开头--验证用户名密码是否正确 31 2、退出是exit或quit--关闭conn,退出接受命令的状态 32 3、其他 33 ''' 34 if clientdatastr.startswith('loginstring'): 35 strlist=clientdatastr.split() 36 namein=strlist[1] 37 passin=strlist[2] 38 if namein in userinfo.keys() and userinfo[namein]==passin: 39 os.chdir('%s\homedir\%s' % (fddir, namein)) 40 conn.send(b'login success...') 41 else: 42 conn.send(b'user name and password wrong......') 43 conn.close() 44 break 45 elif clientdatastr=='exit' or clientdatastr=='quit': 46 conn.close() 47 break 48 elif clientdatastr=='currentdir': 49 curdir=os.getcwd() 50 conn.send(curdir.encode('utf-8')) 51 elif clientdatastr=='currentfiles': 52 curdir=os.getcwd() 53 returnstr='' 54 for root,dirs,files in os.walk(curdir): 55 returnstr+='rootdir:'+root+'\n' 56 for d in dirs: 57 returnstr +='directory:'+d+'\n' 58 for f in files: 59 returnstr +='file:'+f+'\n' 60 print(returnstr) 61 conn.send(returnstr.encode('utf-8')) 62 elif clientdatastr.startswith('downdir'): 63 strlist=clientdatastr.split() 64 dirname=strlist[1] 65 targetdir=os.getcwd()+'\\'+dirname 66 os.chdir(targetdir) 67 curdir=os.getcwd() 68 conn.send(curdir.encode('utf-8')) 69 elif clientdatastr=='updir': 70 fatherdir=os.path.dirname(os.getcwd()) 71 os.chdir(fatherdir) 72 curdir=os.getcwd() 73 conn.send(curdir.encode('utf-8')) 74 elif clientdatastr.startswith('download'): 75 strlist=clientdatastr.split() 76 filename=strlist[1] 77 dirname=os.path.join(os.getcwd(),filename) 78 with open(dirname,'r') as fd: 79 msg=fd.read() 80 conn.send(msg) 81 elif clientdatastr.startswith('upload'): 82 strlist=clientdatastr.split() 83 filename=strlist[1] 84 filecont=strlist[2] 85 dir=os.path.join(os.getcwd(),filename) 86 with open(filename,'w') as fd: 87 fd.write(filecont) 88 conn.send('***') 89 else: 90 cmdstr = clientdatastr.strip() 91 print(cmdstr) 92 result=os.popen(cmdstr) 93 print(result.read()) 94 conn.send(result.read().encode('utf-8'))