博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python第五十四天--第十周作业
阅读量:4568 次
发布时间:2019-06-08

本文共 14745 字,大约阅读时间需要 49 分钟。

SELECT版FTP:

使用SELECT或SELECTORS模块实现并发简单版FTP
允许多用户并发上传下载文件

 

必须使用select or selectors模块支持多并发,禁止使用多线程或多进程

REDMAE

用户登陆 1、查看共享目录文件 2、上传文件, 3、下载方件 4、退出 程序结构: socket_server_client/#程序目录 |- - -clients/#client程序主目录 |      |- - -__init__.py |      |- - -bin/#启用目录 |      |       |- - - __init__.py |      |       |- - -socket_client.py#客户端启动 |      | |      |- - -cfg/#配置文件目录 |      |       |- - - __init__.py |      |       |- - -config.py#配置文件 |      | |      |- - -core/#主要程序目录 |      |       |- - - __init__.py |      |       |- - -client_func.py#主要函数 |      | |      |- - -home/#客户端下载文件目录 | |- - -servers/#server程序主目录 |      |- - -__init__.py |      |- - -bin/#启用目录 |      |       |- - - __init__.py |      |       |- - -registration.py#用户注册 |      |       |- - -server.py#服务端启动(selectors版) |      |       |- - -socket_server.py#服务端启动(select版) |      | |      |- - -cfg/#配置文件目录 |      |       |- - - __init__.py |      |       |- - -config.py#配置文件 |      | |      |- - -core/#主要程序目录 |      |       |- - - __init__.py |      |       |- - -server_classc.py#主要函数 |      | |      |- - -db/#用户上传文件主目录 |              |- - -user_file/#用户上传目录(共享) |              |- - -user_names#注册用户文件 |
程序结构: socket_server_client/#程序目录 |- - -clients/#client程序主目录 |      |- - -__init__.py |      |- - -bin/#启用目录 |      |       |- - - __init__.py |      |       |- - -socket_client.py#客户端启动
(2016/06/26修改,去收发大文件异常)
1 #!usr/bin/env python  2 #-*-coding:utf-8-*-  3 # Author calmyan  4   5 import socket,os,json,sys  6 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#获取相对路径转为绝对路径赋于变量  7 sys.path.append(BASE_DIR)#增加环境变量  8 from core.client_func import user_pwd  9 #from core.client_func import show_process 10 from cfg import config 11  12 #进度条 13 def show_process(lens): 14     received_size=0#定义大小 15     current_percent=0#当前大小百分比 16     while received_size
current_percent: 18 print('#',end='',flush=True) 19 current_percent=int((received_size/lens)*100) 20 new_size=yield 21 received_size+=new_size 22 23 server_addr=('localhost',9500)#设置绑定的 IP 端口 24 #server_addr=('192.168.11.50',9500)#设置绑定的 IP 端口 25 client=socket.socket() 26 client.connect(server_addr) 27 while True: 28 data_d=user_pwd(client) 29 if data_d['tag']:#运行#用户名登陆成功 30 while True: 31 print('''=====指令提示==== 32 查看目录文件: ls 33 下载文件: get 文件名 或 文件编号 如: get test.txt 或 get 1 34 上传方件: put 路径/文件名 如 put e:/test.txt 35 退出:exit 36 ''') 37 cho=input('指令 >>:').strip() 38 if len(cho)==0:continue 39 if cho=='exit':exit()#退出指令 40 cmd_list=cho.split() 41 if cmd_list[0]=='put':#如果等于下载指令 42 if len(cmd_list)==1: 43 print('没有输入相关文件名') 44 continue 45 filename=cmd_list[1] 46 file_dir=config.USER_DIR+'/'+filename 47 if os.path.isfile(file_dir):#如果文件存在 48 file_obj=open(file_dir,"rb")#打开文件 49 name=file_obj.name.split('/')[-1]#文件名 50 #name=filename.split("\\")[-1]#文件名 51 sez=os.path.getsize(file_dir)#获取文件大小 52 if sez<1: 53 print('\033[41;1m文件为空!,不能上传\033[0m') 54 continue 55 progress = show_process(sez) #进度条 传入文件大小 56 progress.__next__() 57 rat=0 58 file_obj.seek(rat)#移动到位置 59 data_header={ 60 "action":"put", 61 "filename":name, 62 "size":sez 63 } 64 65 client.send(json.dumps(data_header).encode())#用json 序列化后,发送相关 信息 66 attr=client.recv(100) 67 print("文件[%s]发送中...."%data_header["filename"]) 68 while rat
View Code

 

|      |- - -cfg/#配置文件目录 |      |       |- - - __init__.py |      |       |- - -config.py#配置文件
1 #!usr/bin/env python 2 #-*-coding:utf-8-*- 3 # Author calmyan 4  5 import os ,sys 6 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#获取相对路径转为绝对路径赋于变量 7 sys.path.append(BASE_DIR)#增加环境变量 8  9 10 USER_DIR=BASE_DIR+'/home'#定义用户目录文件路径变量11 IP='192.168.11.50'12 PORST=9500
View Code
|      |- - -core/#主要程序目录 |      |       |- - - __init__.py |      |       |- - -client_func.py#主要函数
1 #!usr/bin/env python 2 #-*-coding:utf-8-*- 3 # Author calmyan 4 import socket,os,json,sys 5 #用户名登陆函数 6 def user_pwd(client): 7     user_=input('请输入用户名:').strip() 8     pwd_=input('请输入密码:').strip() 9     data_header={10                 "action":"user",11                 "name":user_,12                 "pwd":pwd_13             }14     client.send(json.dumps(data_header).encode())#用json 序列化后,发送相关 信息15     data=client.recv(4096)#接收数据 指令16     data_s=json.loads(data.decode('utf-8'))#反序列17     return data_s
View Code
|- - -servers/#server程序主目录 |      |- - -__init__.py |      |- - -bin/#启用目录 |      |       |- - - __init__.py |      |       |- - -registration.py#用户注册
1 #!usr/bin/env python 2 #-*-coding:utf-8-*- 3 # Author calmyan 4 import socket,os,json,sys,pickle 5  6 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#获取相对路径转为绝对路径赋于变量 7 sys.path.append(BASE_DIR)#增加环境变量 8 from cfg import config 9 print('用户注册'.center(60,'='))10 while True:11     user_=input('请输入您要注册的用户名:').strip()12     user_dir=os.path.join(config.USER_DIR,user_)#拼接用户目录路径13     if os.path.isdir(user_dir):# 判断一个目录是否存在14         print('用户已经存在请重输!')15         continue16     else:17         pwd_=input('请输入密码:').strip()18         pwd_two=input('请确认密码:').strip()19         if pwd_==pwd_two:20 21 22             if  not os.path.isfile(config.USER_FILE):23                 with open(config.USER_FILE,'w',encoding='utf-8') as f:24                     f.write('{}')25             with open(config.USER_FILE,'r+',encoding='utf-8') as f:26                 data=eval(f.readline())27                 data[user_]=pwd_28                 f.seek(0)29                 f.write(str(data))30             print('用户[%s]注册成功!'%user_)31             exit()
View Code
|      |       |- - -server.py#服务端启动(selectors版)(2016/06/26修改,去收发大文件异常)
1 #!usr/bin/env python 2 #-*-coding:utf-8-*- 3 # Author calmyan  4 #python  5 #2017/6/24    19:34 6 #__author__='Administrator' 7 import select,socket,sys ,queue,json,os 8 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#获取相对路径转为绝对路径赋于变量 9 sys.path.append(BASE_DIR)#增加环境变量10 11 import core12 from core.server_class import socket_server13 14 s=socket.socket()#实例化一个连接对象15 s.setblocking(0)#设置成非阻塞16 server_addr=('localhost',9500)#设置绑定的 IP 端口17 s.bind(server_addr)#连接对象绑定IP 端口18 s.listen(100)#队列  可连接数量19 inputs=[s,]#首先要监测本身20 21 outputs=[]#发送列表22 23 meg_queues={} #发送 连接对象的队列集合  字典24 25 while True:26     print('监听中......')27     readable,writeable,exeptional=select.select(inputs,outputs,inputs)#生成select 对象,返回三个列表 连接,发关,错误28 29     for i in readable: #i为一个socket30         if i is s:#如果i 是s 表示有新 连接 进来31             conn,client_addr=i.accept()#建立一个新连接32             print('接入一个新连接...',client_addr)33             conn.setblocking(1)#设成 阻塞34             inputs.append(conn)#加入select,的连接列表,避免出现阻塞35             meg_queues[conn]=queue.Queue()#创建一个队列  添加到字典36         else:37             try:38                 data=i.recv(1024)#如果不是新连接就收数据39             except Exception as e:40                 print(e)41             if data: #如果数据不为空42                 print('[%s] 发来的数据 [%s]'%(i.getpeername,data))43                 meg_queues[i].put(data)#当前连接的消息队列加入数据44                 if i not in outputs:#如果当前连接没有在发送列表内,就加入发送列表45                     outputs.append(i)46             else:47                 print('客户端已经断开了....')#开始清理工作48                 if i in outputs:#在发送列表49                     outputs.remove(i)#在发送列表内删除50                 inputs.remove(i)#在连接列表内删除51                 del meg_queues[i]#在队列字典内删除52 53     for w in writeable:#循环发送列表54         try:55             msg=meg_queues[w].get_nowait()#取出队列中的数据,判断56         except queue.Empty:#如果数据为空57             outputs.remove(w)##从发送列表内删除58         else:59             data = json.loads(msg.decode())#反序列60             serv=socket_server(data,w)61             if data['action']=='user':#如果是用户名,进行认证\62                 #serv=socket_server(data,conn)63                 ret=serv.ret_l()64                 if ret['tag']:65                     pass66                 else:67                     break68             #print('echoing', repr(data), 'to', conn)69             #data=json.loads(data)70             if data['action']=="put":#如果接收的字典中是put,就是进行接收71                 #serv=socket_server(data,conn)72                 serv.put_file(serv.open_f())#调对象方法73             elif data['action']=='get':#下载74                 #serv=socket_server(data,conn)#实例化75                 serv.send_file(serv.open_f())#调 用方法76             elif data['action']=='ls':#查看77                 #serv=socket_server(data,conn)78                 serv.ls_file(serv.open_f())79                 break80 81             #w.send(msg)#发送82 83 84 85     for e in exeptional:#循环错误列表86         print('连接[%s]出错!'%e.getpeername)87         inputs.remove(e)##从发送列表内删除88         if e in outputs:#在发送列表89             outputs.remove(e)#在发送列表内删除90         e.close()91         del meg_queues[e]#在队列字典内删除
View Code
|      |       |- - -socket_server.py#服务端启动(select版)(2016/06/26修改,去收发大文件异常)
1 #!usr/bin/env python 2 #-*-coding:utf-8-*- 3 # Author calmyan 4 import socket,os,json 5 import sys 6 import selectors 7  8 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#获取相对路径转为绝对路径赋于变量 9 sys.path.append(BASE_DIR)#增加环境变量10 11 from  core.server_class import socket_server12 from  core.server_class import open_file_list13 14 15 16 17 18 def accept(sock, mask):19     conn, addr = sock.accept()  # 建立新连接20     print('accepted', conn, 'from', addr)21     conn.setblocking(1)#设成非阻塞22     sel.register(conn, selectors.EVENT_READ, read)#注册 连接,回调函数 read23 24 25 def read(conn,mask):26     #gevent.spawn(handle_request, cli)#创建一个新协程来27     data = conn.recv(1024)  # 接收数据28     if data:#不为空29         print('接收的数据:',data)30         #print(mask)31         if len(data)==0:32             return33         data = json.loads(data.decode())#反序列34         serv=socket_server(data,conn)35         if data['action']=='user':#如果是用户名,进行认证\36             #serv=socket_server(data,conn)37             ret=serv.ret_l()38             if ret['tag']:39                 pass40             else:41                 return42         elif data['action']=="put":#如果接收的字典中是put,就是进行接收43             #serv=socket_server(data,conn)44             serv.put_file(serv.open_f())#调对象方法45             return46         elif data['action']=='get':#下载47             #serv=socket_server(data,conn)#实例化48             serv.send_file(serv.open_f())#调 用方法49             return50         elif data['action']=='ls':#查看51             #serv=socket_server(data,conn)52             serv.ls_file(serv.open_f())53             return54         else:55             return56     else:#如果为空57         print('closing', conn)58         sel.unregister(conn)#取消注册59         conn.close()#关闭连接60 61 server_addr=('0.0.0.0',9500)#设置绑定的 IP 端口62 s=socket.socket()#定义63 s.bind(server_addr)#绑定IP 端口64 s.listen(5)#对列565 s.setblocking(False)#非阻塞66 print('正在监听中')67 68 sel = selectors.DefaultSelector()#生成一个创建一个selectors对象69 sel.register(s, selectors.EVENT_READ, accept)#注册连接  返调函数为accepts70 71 while True:72         events = sel.select()#默认为阻塞模式73         for key, mask in events:#如果有连接,接入74             callback = key.data#新建连接句柄75             callback(key.fileobj, mask)
View Code
|      |- - -cfg/#配置文件目录
|      |       |- - - __init__.py |      |       |- - -config.py#配置文件
1 #!usr/bin/env python 2 #-*-coding:utf-8-*- 3 # Author calmyan 4 import os ,sys 5 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#获取相对路径转为绝对路径赋于变量 6 sys.path.append(BASE_DIR)#增加环境变量 7  8  9 USER_DIR=BASE_DIR+'/db/user_file/'#定义用户目录文件路径变量10 11 USER_FILE=BASE_DIR+'/db/user_names'#定义用户名密码文件路径变量12 IP='localhost'13 PORST=9501
View Code
|      |- - -core/#主要程序目录 |      |       |- - - __init__.py |      |       |- - -server_classc.py#主要函数(2016/06/26修改,去收发大文件异常)
1 #!usr/bin/env python  2 #-*-coding:utf-8-*-  3 # Author calmyan  4 import socket,os,json,sys,pickle  5 import selectors  6   7 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#获取相对路径转为绝对路径赋于变量  8 sys.path.append(BASE_DIR)#增加环境变量  9  10 from cfg import config 11  12  13 #用户名检测函数 14  15 def open_file_list(name,pas):#传入当前类 16     with open(config.USER_FILE,'r',encoding='utf-8') as f: 17         data=eval(f.readline()) 18         print(data) 19         if name in data and pas==data[name]: 20             return True 21         else: 22             return False 23  24  25  26  27 #连接类 28 class socket_server(object): 29     '''连接类''' 30     file_path=config.USER_DIR#用户路经变量 31     def __init__(self,data,conn):#传入 32         self.DATA=data 33         self.conn=conn 34  35  36     def ret_l(self): 37         self.ret=self.login(self.DATA["name"],self.DATA['pwd'],self.conn)#用户名检测 38         return self.ret 39     def open_f(self):#打开目录 40  41         file_dir=os.path.join(config.USER_DIR)#用户目录 42         print(file_dir) 43         file_name=os.listdir(file_dir)#目录文件列表 44         f=file_dir+'/'+self.DATA['filename']##上传的文件名 45         return file_dir,file_name,f#返回 46  47     def ls_file(self,data):#查看文件 48         self.conn.send('为了防粘包'.encode('utf-8'))#防粘包 49         #self.conn.recv(100) 50         self.conn.send(json.dumps(data[1]).encode()) 51         return 52  53     def send_file(self,data): 54  55         if self.DATA['filename'] in data[1]:#如果是输入文件名 56             f=data[0]+'/'+self.DATA['filename'] 57             file_obj=open(f,"rb")#打开文件 58             name=file_obj.name.split('/')[-1]#文件名 59             sez=os.path.getsize(f)#获取文件大小 60  61             if sez<1: 62                 print('文件错误!') 63                 self.DATA['filename']=False 64                 self.conn.send(json.dumps(self.DATA).encode()) 65                 return 66             print(''.center(30,'=')) 67             print(sez) 68             print(''.center(30,'=')) 69             data_header={ 70                     "action":"put", 71                     "filename":name, 72                     "size":sez 73                     } 74             #self.conn.send(b'1') 75             self.conn.send(json.dumps(data_header).encode())#用json 序列化后,发送相关 信息 76             self.conn.recv(100) 77             file_siez=0 78             while file_siez
View Code

 

 
 
 

转载于:https://www.cnblogs.com/uge3/p/7077632.html

你可能感兴趣的文章
找茬脚本思路(修改中)
查看>>
Java创建线程的细节分析
查看>>
python语法_深浅拷贝
查看>>
使用CCleaner卸载chrome
查看>>
typeof和GetType的区别
查看>>
xtraTabbedMdiManager控件切换时控件不更新的问题
查看>>
为易信正名
查看>>
debian8.4 ibus中文输入法
查看>>
如何使用dos命令查看MySQL当前使用的数据库?
查看>>
猫眼电影爬取(一):requests+正则,并将数据存储到mysql数据库
查看>>
android的ArrayMap类
查看>>
2011年5款备受关注的开源 NoSQL 数据库
查看>>
2-4-1 元组
查看>>
476. Number Complement(补数)
查看>>
[HNOI2015]落忆枫音
查看>>
生成函数
查看>>
HTMl5的存储方式sessionStorage和localStorage详解
查看>>
BZOJ 4516: [Sdoi2016]生成魔咒——后缀数组、并查集
查看>>
《JAVA程序设计》实训第一天——《猜猜看》游戏
查看>>
普通用户 crontab 任务不运行
查看>>