python第五十四天--第十周作業

来源:http://www.cnblogs.com/uge3/archive/2017/06/25/7077632.html
-Advertisement-
Play Games

SELECT版FTP:使用SELECT或SELECTORS模塊實現併發簡單版FTP允許多用戶併發上傳下載文件 必須使用select or selectors模塊支持多併發,禁止使用多線程或多進程 REDMAE 1 #!usr/bin/env python 2 #-*-coding:utf-8-*- ...


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#客戶端啟動
  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<lens:
 17         if int((received_size/lens)*100)>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                     client.send(json.dumps(data_header).encode())#用json 序列化後,發送相關 信息
 65 
 66                     print("文件[%s]發送中...."%data_header["filename"])
 67 
 68                     while rat<sez:
 69                         line=file_obj.read(4096)
 70                         client.send(line)
 71                         try:
 72                             progress.send(len(line))#傳入當前數據大小
 73                         except StopIteration as e:
 74                             print("100%")
 75                             break
 76                     print("文件[%s]發送完畢!"%data_header["filename"])
 77                 else:
 78                     print('\033[41;1m該文件不存在或為目錄\033[0m')
 79                     continue
 80             elif cmd_list[0]=='get':#如果等於get 上傳指令
 81                 if len(cmd_list)==1:
 82                     print('沒有輸入相關文件名')
 83                     continue
 84                 filename=cmd_list[1]
 85                 print(filename)
 86                 data_header={
 87                         "action":"get",
 88                         "filename":filename,
 89                         "size":''
 90                     }
 91                 client.send(json.dumps(data_header).encode())#用json 序列化後,發送相關 信息
 92                 datas=client.recv(4096)#接收數據 指令
 93                 data_l= json.loads(datas.decode())#反序列
 94                 # print(data_l)
 95                 # print(data_l['size'])
 96                 if data_l['filename']==False:
 97                     print('\033[41;1m文件不存在或者出錯\033[0m')
 98                     continue
 99                 prten=show_process(data_l["size"])
100                 prten.__next__()
101                 file_dir=config.USER_DIR+'/'+data_l["filename"]
102                 file_obj=open(file_dir,'wb')#打開新建 這個文件
103                 rece_size=0#定義 文件大小值
104 
105 
106                 while rece_size<data_l["size"]:#小於接收的文件大小時,
107                     recv_data=client.recv(4096)
108                     file_obj.write(recv_data)#寫入文件
109                     rece_size+=len(recv_data)#增加文件大小計算
110                     try:
111                         prten.send(len(recv_data))
112                     except StopIteration as e:
113                         print('100%')
114 
115                 else:
116                     print("文件[%s]接收完畢!"%data_l["filename"])
117                     file_obj.flush()
118                     file_obj.close()#關閉文件
119             elif cmd_list[0]=='ls':#查看目錄文件
120                 data_header={
121                         "action":"ls",
122                         "filename":'',
123                         "size":''
124                     }
125                 client.send(json.dumps(data_header).encode())#用json 序列化後,發送相關 信息
126                 datas=client.recv(4096)#接收數據 指令
127                 data_l= json.loads(datas.decode())#反序列
128                 for k,v in enumerate(data_l):
129                     print('編號: %s  文件名:%s'%(k,v))
130 
131     else:
132         print(data_d['mag'])
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         continue
16     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版)
 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 core
12 from core.server_class import socket_server
13 
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為一個socket
30         if i is s:#如果i 是s 表示有新 連接 進來
31             conn,client_addr=i.accept()#建立一個新連接
32             print('接入一個新連接...',client_addr)
33             conn.setblocking(0)#也設成非阻塞
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                     pass
66                 else:
67                     break
68             #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                 break
80 
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版)
 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_server
12 from  core.server_class import open_file_list
13 
14 
15 
16 
17 
18 def accept(sock, mask):
19     conn, addr = sock.accept()  # 建立新連接
20     print('accepted', conn, 'from', addr)
21     conn.setblocking(False)#設成非阻塞
22     sel.register(conn, selectors.EVENT_READ, read)#註冊 連接,回調函數 read
23 
24 
25 def read(conn,mask):
26     #gevent.spawn(handle_request, cli)#創建一個新協程來
27     data = conn.recv(1024)  # 接收數據
28     if data:#不為空
29         print('接收的數據:')
30         #print(mask)
31         if len(data)==0:
32             return
33         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                 pass
40             else:
41                 return
42         if data['action']=="put":#如果接收的字典中是put,就是進行接收
43             #serv=socket_server(data,conn)
44             serv.put_file(serv.open_f())#調對象方法
45         elif data['action']=='get':#下載
46             #serv=socket_server(data,conn)#實例化
47             serv.send_file(serv.open_f())#調 用方法
48         elif data['action']=='ls':#查看
49             #serv=socket_server(data,conn)
50             serv.ls_file(serv.open_f())
51             return
52     else:#如果為空
53         print('closing', conn)
54         sel.unregister(conn)#取消註冊
55         conn.close()#關閉連接
56 
57 server_addr=('0.0.0.0',9501)#設置綁定的 IP 埠
58 s=socket.socket()#定義
59 s.bind(server_addr)#綁定IP 埠
60 s.listen(5)#對列5
61 s.setblocking(False)#非阻塞
62 print('正在監聽中')
63 
64 sel = selectors.DefaultSelector()#生成一個創建一個selectors對象
65 sel.register(s, selectors.EVENT_READ, accept)#註冊連接  返調函數為accepts
66 
67 while True:
68         events = sel.select()#預設為阻塞模式
69         for key, mask in events:#如果有連接,接入
70             callback = key.data#新建連接句柄
71             callback(key.fileobj, mask)
View Code
|      |- - -cfg/#

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • JSON-lib包(最關鍵的兩個類分別是JSONObject和JSONArray)完成對json的構造和一些基本方法的使用。 二者區別: ①JSONObject構造的字元串是鍵值對形式(key:value),多個鍵值對間以英文逗號連接; ②JSONArray構造的字元串是數組形式([array1,a ...
  • 反射的基本概述 一個class文件被載入到記憶體的時候,JVM就會經行解剖,把這個class文件的所有成員全部解剖出來,然後JVM會創建一個Class對象,把這些成員信息全部都封裝起來,所謂反射就是指:我們獲取到這個Class對象,就相當於獲取到了該類的所有成員信息,我們就能操又該類的所有成員. Ja ...
  • 無意間碰到的一個大神整理的Python學習思維導圖,感覺對初學者理清學習思路大有裨益,非常感謝他的分享。 詳情見:https://woaielf.github.io/2017/06/13/python3-all/ 14 張思維導圖 基礎知識 數據類型 序列 字元串 列表 & 元組 字典 & 集合 條 ...
  • /* 工作單元 這個模式涉及到了領域模型、數據映射器和標識映射,這裡就統一進行整理和回顧了。 $venue = new \woo\domain\Venue(null,"The Green Tree"); \woo\domain\ObjectWatcher::instance()->performOp... ...
  • 分享 知識要點:lubridate包拆解時間 | POSIXlt利用決策樹分類,利用隨機森林預測利用對數進行fit,和exp函數還原 訓練集來自Kaggle華盛頓自行車共用計劃中的自行車租賃數據,分析共用自行車與天氣、時間等關係。數據集共11個變數,10000多行數據。https://www.kag ...
  • 【數組基礎】【數組遍歷】【超全局數組】【數組功能】【數組函數】 ...
  •  也不知道這個標題中的原則一詞用的對不對,我姑且叫他原則吧。對於寫代碼的我們來說,其實我後面會叫他規範,但是想了想,對於其他方面來說,又或許是原則,好啦,不糾結,直接進入正題。  來新公司一個多月了,從我剛到公司那天剛好是一個迭代的開始,直到昨天,後臺版本已經同步到公網,APP因 ...
  • 題目鏈接 Problem Description In mathematics, the four color theorem, or the four color map theorem, states that, given any separation of a plane into cont ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...