#server代码
import socketserver,os,hashlib Base_paht = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + '/db' class Server_ftp(socketserver.BaseRequestHandler):
def handle(self):
while 1:
try:
self.username = self.request.recv(1024).strip() #接受用户信息
if not self.username:continue
self.username_path = Base_paht + '/%s/' % self.username.decode() #获取用户文件地址
print(self.username.decode(), '连接成功!') #打印用户连接信息
self.request.send('连接服务器成功!'.encode())
while 1:
try:
self.data = self.request.recv(1024).strip() #接受客户端命令
print('-->',self.data)
if not self.data :continue
print('{} wrote:'.format(self.client_address[0]),self.username)#打印ip及用户名称
cmd_dic = self.data.decode() #命令编码
print('执行的命令为',cmd_dic)
if hasattr(self,cmd_dic + '_file'): #判断是否存在这条命令
self.request.send('{}命令可以被执行'.format(cmd_dic).encode())
func = getattr(self,cmd_dic + '_file') #反射
func()
else:
self.request.send('no'.encode()) #不存在发送错误信息
except ConnectionResetError as e:
# print('err',e)
break
except ConnectionResetError as e:
print(self.client_address[0],e)
break
def get_file(self):
filename = self.request.recv(1024).decode()
print('客户端想要获取的文件名称为:',filename)
if os.path.isfile(self.username_path + filename) :
file_size = os.stat(self.username_path + filename).st_size #确认文件大小
self.request.send(str(file_size).encode()) #发送文件大小
self.request.recv(1024) #接收please give me
f = open(self.username_path + filename,'rb')
self.request.send(f.read())
f.close()
confirm = self.request.recv(1024).decode()
print(confirm)
f_1 = open(self.username_path + filename, 'rb')
m2 = hashlib.md5()
m2.update(f_1.read())
f_1_m2 = m2.hexdigest()
f.close()
self.request.send(f_1_m2.encode())
print(self.request.recv(1024).decode()) else:
self.request.send('no'.encode()) #如果文件不存在,发送no信息
def put_file(self):
filename = self.request.recv(1024).decode()
if filename != 'no' :
self.request.send('服务器收到文件名称!'.encode())
file_size = self.request.recv(1024).decode()
self.request.send('服务器收到文件大小为{}'.format(file_size).encode())
f = open(self.username_path + filename,'wb') #直接写入,如果有就覆盖
confirm_size = 0
while confirm_size < int(file_size):
if int(file_size) - confirm_size > 1024: # 确保接受的准确性,拒绝粘包.
cal = 1024
else:
cal = int(file_size) - confirm_size
data = self.request.recv(cal)
confirm_size += len(data)
f.write(data)
f.close()
f_1 = open(self.username_path + filename,'rb')
m2 = hashlib.md5()
m2.update(f_1.read())
f_1_m2 = m2.hexdigest()
f_1.close()
self.request.send(f_1_m2.encode())
print(self.request.recv(1024).decode())
self.request.send('{}上传完成'.format(filename).encode()) # 返回服务器信息,表示下载完成 else:
print('客户端传送错误文件名称!') def open_file(self):
filename = self.request.recv(1024).decode()
self.request.send('服务器收到目录名称!'.encode())
self.request.recv(1024) #防止粘包
if os.path.exists(self.username_path + filename ):
self.request.send('yes'.encode())
self.request.recv(1024)
path_dir = os.listdir(self.username_path+ filename)
if path_dir == []: # 如果为空
self.request.send('nothing'.encode())
else:
self.request.send(str(path_dir).encode())
else:
self.request.send('no'.encode()) def look_file(self):
self.request.recv(1024) #接收返回的数据,防止粘包
path_dir = os.listdir(self.username_path)
if path_dir == []: #如果为空
self.request.send('nothing'.encode())
else:
self.request.send(str(path_dir).encode()) if __name__ =='__main__':
HOST,PORT = 'localhost' , 6969
server = socketserver.ThreadingTCPServer((HOST,PORT),Server_ftp)
print('----------->等待连接<------------')
server.serve_forever()
#client代码

import socket,os,pickle,hashlib,sys

floder_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + '/user_floder'
user_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + '/conf'
server_db_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + '/server_ftp/db/' class Scoket_ftp(object):
# 客户端类
def __init__(self):
self.client = socket.socket() def client_user_register(self):
#用户注册
username = input('请输入用户名:').strip()
password = input('请输入密码:').strip()
if not os.path.exists(user_path + '/%s'%username) :
pwd_md = hashlib.md5() #md5加密用户密码
pwd_md.update(bytes(password,encoding='utf-8'))
pwd_save = pwd_md.hexdigest()
pickle.dump({'username':username,'password':pwd_save},open(user_path + '/%s'%username,'wb'))
os.makedirs(server_db_path + username)
print('创建成功!')
else:
print('账户已经存在!') def client_user_login(self):
#身份验证
username = input('请输入用户名:').strip()
password = input('请输入密码:').strip()
if os.path.exists(user_path + '/%s'%username) :
pwd_md = hashlib.md5() # md5加密用户密码
pwd_md.update(bytes(password,encoding='utf-8'))
pwd_save = pwd_md.hexdigest()
user_dic = pickle.load(open(user_path + '/%s'%username,'rb'))
if username == user_dic['username'] and pwd_save == user_dic['password'] :
print('%s登录成功'%username)
return username
else:
print('账户密码错误!')
return False
else:
print('账户密码错误!')
return False def client_conn(self,ip_addr,port):
#建立连接
while 1:
username = self.client_user_login()
if username :
self.client.connect((ip_addr, port))
self.client.send(username.encode())
print(self.client.recv(1024).decode())
break
else:
continue def help(self):
#帮助信息
print('''
-----------help-----------
look:查看当前目录下文件
open foldername:打开文件夹
get filename:下载文件
put filename:上传文件
''')
def client_interaction(self):
#交互
while 1:
self.help()
cmd = input('请输入操作命令:').strip()
if len(cmd.split()) == 1: #判断命令行长度,如果是1的话,在判断输入
if cmd == 'look': self.file_look()#使用look方法
elif cmd == 'exit':
self.file_exit()
else:
print('命令输入错误,请重新输入')
continue
elif len(cmd.split()) == 2: #长度为2,证明是带有前面的语句的
cmd_option, filename = cmd.split()
if hasattr(self,'file_' + cmd_option):
func = getattr(self,'file_' +cmd_option)
func(filename)
else:
continue
else:
continue
def file_look(self):
#查看
self.client.send('look'.encode()) #发送方法
print(self.client.recv(1024).decode()) # 服务器确认信息,后面可以加入判断,判断服务器目前状态是否正常
self.client.send('please give me!'.encode()) # 自动发送给服务器
print('文件目录:',self.client.recv(1024).decode()) #接收目录信息并打印
def file_get(self,filename):
#下载
self.client.send('get'.encode()) #先发送方法
print(self.client.recv(1024).decode()) #服务器确认信息,后面可以加入判断,判断服务器目前状态是否正常
self.client.send(filename.encode()) #再发送文件名称
confirm = self.client.recv(1024).decode() #服务器确认文件是否存在,如果存在返回文件大小,如果不存在,返回no
if confirm != 'no':
self.client.send('please give me!'.encode())
f = open(floder_path+'/'+filename,'wb') #在下载文件夹中创建该文件(如果存在,则替换)
confirm_cal = 0
rate = 1
while confirm_cal < int(confirm):
if int(confirm) - confirm_cal > 1024: #确保接受的准确性,拒绝粘包.
cal = 1024
else:
cal = int(confirm) - confirm_cal
data = self.client.recv(cal)
confirm_cal += len(data) #避免tcp拆包
f.write(data)
if int(confirm) > 102400:
if confirm_cal > int(confirm)/100*(rate+1) and rate<= 100 :
rate += 1
r = '\r[%s]%d%%' % ("=" * rate, rate)
sys.stdout.write(r)
sys.stdout.flush()
else:
continue
else:
r = '[%s]%d%%'%('='*100,100)
sys.stdout.write(r)
f.close()
self.client.send('{}下载完成'.format(filename).encode()) # 返回服务器信息,表示下载完成
f_1 = open(floder_path+'/'+filename,'rb') #判断一致性
m2 = hashlib.md5()
m2.update(f_1.read())
f_1_m2 = m2.hexdigest()
f_1.close()
f_1_m2_server = self.client.recv(1024).decode()
if f_1_m2 == f_1_m2_server :
print('\n下载完成!')
self.client.send('客户端已经成功获取完整文件!'.encode())
else:
print('传输异常')
self.client.send('客户端获取文件不完整或存在异常!'.encode())
else:
print('确认信息为no,文件可能不存在或有其他问题!') def file_put(self,filename):
#上传文件
self.client.send('put'.encode()) # 先发送方法
print(self.client.recv(1024).decode()) # 服务器确认信息,后面可以加入判断,判断服务器目前状态是否正常
if os.path.isfile(floder_path + '/' + filename):
self.client.send(filename.encode())
print(self.client.recv(1024).decode()) #拒绝粘包
cal = os.stat(floder_path + '/' + filename).st_size #获取文件大小
self.client.send(str(cal).encode()) #发送文件大小信息
print(self.client.recv(1024).decode()) #获取反馈
f = open(floder_path+'/'+filename,'rb') #打开文件
self.client.send(f.read())
f.close()
f_1 = open(floder_path + '/' + filename, 'rb') #一致性校验
m2 = hashlib.md5()
m2.update(f_1.read())
f_1_m2 = m2.hexdigest()
f_1.close()
f_1_m2_server = self.client.recv(1024).decode()
if f_1_m2 == f_1_m2_server:
print('上传完成!')
self.client.send('客户端已经成功上传完整文件!'.encode())
else:
print('传输异常')
self.client.send('客户端上传文件不完整或存在异常!'.encode())
print(self.client.recv(1024).decode())
else:
self.client.send('no'.encode())
print('查无此文件')
def file_open(self,filename):
self.client.send('open'.encode()) # 先发送方法
print(self.client.recv(1024).decode()) # 服务器确认信息,后面可以加入判断,判断服务器目前状态是否正常
self.client.send(filename.encode()) #发送目录名称
print(self.client.recv(1024).decode())
self.client.send('防止粘包'.encode())
confirm = self.client.recv(1024).decode() # 服务器确认文件是否存在,如果存在返回yes,如果不存在,返回no
if confirm != 'no':
self.client.send('please give me!'.encode()) #自动发送给服务器
file_dir = self.client.recv(1024).decode()
print(file_dir) else:
print('确认信息为no,目录可能不存在或有其他问题!') if __name__ == '__main__' :
socket_ftp = Scoket_ftp()
option = input('''
---------option----------
1.创建用户
2.登录
3.退出
''').strip()
if option == '':
socket_ftp.client_user_register()
elif option == '':
socket_ftp.client_conn('localhost',6969) socket_ftp.client_interaction()
elif option == '':
exit() else:
print('wrong!')
exit()

python 学习分享-实战篇高级的ftp的更多相关文章

  1. python 学习分享-实战篇简单的ftp

    import socket import os import time import pickle Basedb = os.path.dirname(os.path.dirname(os.path.a ...

  2. python 学习分享-实战篇选课系统

    # 角色:学校.学员.课程.讲师 # 要求: # 1. 创建北京.上海 2 所学校 # 2. 创建linux , python , go 3个课程 , linux\py 在北京开, go 在上海开 # ...

  3. python 学习分享-实战篇类 Fabric 主机管理程序开发

    # 类 Fabric 主机管理程序开发: # 1. 运行程序列出主机组或者主机列表 # 2. 选择指定主机或主机组 # 3. 选择让主机或者主机组执行命令或者向其传输文件(上传/下载) # 4. 充分 ...

  4. python 学习分享-实战篇增删改查作业

    一大波函数来袭 作业要求: 1本次作业通过空格及逗号,将文件拆分成列表,在通过判断add.del.update.select等关键字,来判断用户执行的是哪种命令,根据不同的命令调用不同的函数去处理. ...

  5. python 学习分享-函数篇

    函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但你也可以自己创建函数,这 ...

  6. python 学习分享-字典篇

    python字典(Dictionary) dict是无序的 key必须是唯一切不可变的 a={'key1':'value1','key2':'value2'} 字典的增删改查 a['key3']='v ...

  7. python 学习分享-基础篇

    1.python起手式 写下第一个代码,打印‘hello world’ print('hello world') 2.变量 变量是为了存储信息,在程序中被调用,标识数据名称或类型. 变量定义的规则: ...

  8. python 学习分享-函数篇2

    递归 自己玩自己的函数: 1. 必须有一个明确的结束条件 2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少 3. 递归效率不高,递归层次过多会导致栈溢出 递归例子和二分查找都放在里面了 ...

  9. Python学习笔记基础篇——总览

    Python初识与简介[开篇] Python学习笔记——基础篇[第一周]——变量与赋值.用户交互.条件判断.循环控制.数据类型.文本操作 Python学习笔记——基础篇[第二周]——解释器.字符串.列 ...

随机推荐

  1. hdu-2852 KiKi's K-Number---二分+树状数组

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2852 题目大意: 题意:    给出三种操作,    0 在容器中插入一个数.    1 在容器中删 ...

  2. 1.3配置存储单元(nbu重删池)

    1.3配置存储单元 在备份或归档操作时,NetBackup将数据通过存储单元写到物理介质上,NetBackup支持三种类型的存储单元.即: 介质管理器.磁盘和NDMP. 1.3.1介质管理存储单元配置 ...

  3. 相机标定/校正(Camera Calibration)

    以前DIP課程有做過Camera calibration,這次因為用Gopro做Visual SLAM,所以又要撿一下校正的過程.主要還是張正友的方法. OpenCV: 用OpenCV自帶的Sampl ...

  4. 曲率(Curvature)

    原文链接 几何体的曲率对于不同的对象有不同的定义.首先来看最简单的平面曲线. 首先把曲线分成无穷小的小段,每一段看作某个圆的一小段圆弧.这个圆叫做“密切圆”(Osculating Circle).由于 ...

  5. Linux驱动学习(编写一个最简单的模块)

    在Linux中想做驱动开发,那么一定要先熟悉module的使用和编写 一.什么是module 从名字上看就是模块的意思,我个人的理解就是一个一个的小程序,可以进行动态的安装和卸载,而在这里面就实现一些 ...

  6. rnn,lstm and JuergenSchmidhuber

    JuergenSchmidhuber 是瑞士的一位牛人,主要贡献是rnn, lstm. google的deep mind新作,Human-level control through deep rein ...

  7. Map the Debris -freecodecamp算法题目

    Map the Debris 1.要求 返回一个数组,其内容是把原数组中对应元素的平均海拔转换成其对应的轨道周期. 原数组中会包含格式化的对象内容,像这样 {name: 'name', avgAlt: ...

  8. 牛客小白月赛2 E 是是非非 【尼姆博弈】

    链接:https://www.nowcoder.com/acm/contest/86/E来源:牛客网 题目描述 坎为水,险阳失道,渊深不测:离为火,依附团结,光明绚丽. 坎卦:水洊至,习坎:君子以常德 ...

  9. 利用sysbench进行MySQL OLTP基准测试

      Preface       In order to know clearly about the real performance threshold of database server,we ...

  10. python代码实现截图识字

    有次网上down了个截图实识的软件,发现一天只能用10次要钱才能解锁免费,很气,作为一个菜鸡怎么能忍受 于是自己用python写了个简单的小工具,分享给大家 代码如下: 先安装库 from PIL i ...