#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. IOS 单例模式(非ARC)

    singleton_h :连接字符串和参数 // ## : 连接字符串和参数 #define singleton_h(name) + (instancetype)shared##name; #defi ...

  2. Uva 11732 strcmp()函数

    题目链接:https://vjudge.net/contest/158125#problem/A 题意: 系统中,strcmp函数是这样执行的,给定 n 个字符串,求两两比较时,strcmp函数要比较 ...

  3. 2018.7.9 Android—显式Intent和隐式Intent的区别

    1:都是用来在一个activity中启动另外一个activity 2:显示Intent直接指明要启动activity的定义,即activity.class:隐式intent通过在androidmani ...

  4. vue input框设置值 一般对象都是通过打点形式取值

  5. Python 爬虫的工具列表

    这个列表包含与网页抓取和数据处理的Python库 网络 通用 urllib -网络库(stdlib). requests -网络库. grab - 网络库(基于pycurl). pycurl - 网络 ...

  6. Could not autowire. No beans of 'TbAssetsMapper' type found. less... (Ctrl+F1) Inspection info:Checks autowiring problems in a bean class.

    报错:Could not autowire. No beans of 'TbAssetsMapper' type found. less... (Ctrl+F1) Inspection info:Ch ...

  7. cutil.h问题

    CUDA5.0没有cutil.h头文件,貌似用helper_cuda.h文件代替,暂时没出问题.

  8. IE 8 下小心使用console.log()

    我们很多情况下会使用console.log() 对代码调试.在chrome下和Firefox下都不会有太大问题,但是在最近我在IE8 下调试时使用了console.log(),就出现一些问题.在IE8 ...

  9. ztree3.5中checkbox无法取消选中的问题解决

    使用jquery的tree插件ztree,用到复选框的功能 var setting = { check: { enable: true }, data: { simpleData: { enable: ...

  10. input属性总结

    <input type="text" readonly="readonly" /> 这个是不能输入的 readonly="readonly ...