1. 程式人生 > >ftp(網路傳輸)--BaseRequesHandler(tcp協議下的多個客戶端連線)--urandom(隨機生成位元組字串)--hmac(類似於hashlib)

ftp(網路傳輸)--BaseRequesHandler(tcp協議下的多個客戶端連線)--urandom(隨機生成位元組字串)--hmac(類似於hashlib)

ftp(網路傳輸,下載)簡單例項:

server服務端:

# server 服務端
import json
import socket
import struct

server = socket.socket()
server.bind(("127.0.0.1",8001))
server.listen()
conn,addr = server.accept()
#接收檔案的描述資訊長度
struct_data_len = conn.recv(4)
data_len=struct.unpack("i",struct_data_len)[0]
print("字典的位元組長度為:",data_len)
#設定勺子大小,把字典位元組給取出來 file_info_bytes =server.recv(data_len) #拿到字典的json格式 file_info_json = file_info_bytes.decode("utf-8") #還原回字典 file_info_dict = json.loads(file_info_json) print("字典的內容:",file_info_dict) #根據發來的檔案資訊,準備迴圈接收. recv_sum = 0 #設定檔案的開啟和儲存路徑,with open,會用到 file_path = "D:\s18\jj"+"\\"+file_info_dict["
file_name"] #開始真正接收 with open(file_path,"wb") as f: #迴圈結束的條件是,寫進去的檔案長度比對方給你的檔案長度相等就結束. while recv_sum<file_info_dict["file_size"]: every_recv_data = conn.recv(1024) recv_sum += len(every_recv_data) f.write(every_recv_data)

 

client 客戶端:

import os
import
socket import json import struct client = socket.socket() client.connect(('127.0.0.1',8001)) #統計檔案大小 file_size = os.path.getsize(r'D:\python_workspace_s18\day029\aaa.mp4') #統計檔案描述資訊,給服務端,服務端按照我的檔案描述資訊來儲存檔案,命名檔案等等,現在放到一個字典裡面了 file_info = { 'file_name':'aaa.mp4', 'file_size':file_size, } #由於字典無法直接轉換成bytes型別的資料,所以需要json來將字典轉換為json字串.在把字串轉換為位元組型別的資料進行傳送 #json.dumps是將字典轉換為json字串的方法 file_info_json = json.dumps(file_info) #將字串轉換成bytes型別的資料 file_info_byte = file_info_json.encode('utf-8') #為了防止黏包現象,將檔案描述資訊的長度打包後和檔案的描述資訊的資料一起傳送過去 data_len = len(file_info_byte) #把字典的位元組長度封包成4個位元組.方便對方接收後面的字典訊息 data_len_struct = struct.pack('i',data_len) #把字典的位元組長度和字典的位元組一起傳送過去,對方先接受的是字典的長度,然後此訊息,改變下次接收的位元組流大小,就能拿到字典內容,
#而自己,不需要擔心,對方把字典資訊和我傳送的檔案內容相混.
client.send(data_len_struct + file_info_byte) #定義一個變數,=0,作為每次讀取檔案的長度的累計值 sum = 0 #開啟的aaa.mp4檔案,rb的形式, with open('aaa.mp4','rb') as f: #迴圈讀取檔案內容 while sum < file_size: #每次讀取的檔案內容,每次讀取1024B大小的資料 every_read_data = f.read(1024) #將sum累加,統計長度 sum += len(every_read_data) #將每次讀取的檔案的真實資料返送給服務端 client.send(every_read_data)

 二、關於socketserver.BaseRequestHandler

該地址與此相關,有時間再仔細研究:

https://www.cnblogs.com/progor/p/8617042.html
 1 import socketserver                              #1、引入模組
 2 class MyServer(socketserver.BaseRequestHandler): #2、自己寫一個類,類名自己隨便定義,然後繼承socketserver這個模組裡面的BaseRequestHandler這個類
 3 
 4     def handle(self):                            #3、寫一個handle方法,必須叫這個名字
 5         #self.request                            #6、self.request 相當於一個conn
 6 
 7         self.request.recv(1024)                  #7、收訊息
 8         msg = '親,學會了嗎'
 9         self.request.send(bytes(msg,encoding='utf-8')) #8、發訊息
10 
11         self.request.close()                     #9、關閉連線
12 
13         # 拿到了我們對每個客戶端的管道,那麼我們自己在這個方法裡面的就寫我們接收訊息傳送訊息的邏輯就可以了
14         pass
15 if __name__ == '__mian__':
16     #thread 執行緒,現在只需要簡單理解執行緒,彆著急,後面很快就會講到啦,看下面的圖
17     server = socketserver.ThreadingTCPServer(('127.0.0.1',8090),MyServer)#4、使用socketserver的ThreadingTCPServer這個類,將IP和埠的元祖傳進去,還需要將上面咱們自己定義的類傳進去,得到一個物件,相當於我們通過它進行了bind、listen
18     server.serve_forever()                       #5、使用我們上面這個類的物件來執行serve_forever()方法,他的作用就是說,我的服務一直開啟著,就像京東一樣,不能關閉網站,對吧,並且serve_forever()幫我們進行了accept
19 
20 
21 #注意:
22 #有socketserver 那麼有socketclient的嗎?
23 #當然不會有,我要作為客戶去訪問京東的時候,京東幫我也客戶端了嗎,客戶端是不是在我們自己的電腦啊,並且socketserver對客戶端沒有太高的要求,只需要自己寫一些socket就行了。
資料(有空再研究,較耗時間)

 

三、os.urandom(n)

隨機生成n個位元組字串的方法

 四.  hmac模組

def hmac_md5(key, s):
    return hmac.new(key.encode('utf-8'), s.encode('utf-8'), 'MD5').hexdigest()

class User(object):
    def __init__(self, username, password):
        self.username = username
        self.key = ''.join([chr(random.randint(48, 122)) for i in range(20)])
        self.password = hmac_md5(self.key, password)