在介紹之前,我們需要了解一個加密算法
MD5 校驗和(checksum)通過對接收的傳輸資料執行散列運算來檢查資料的正确性。計算出的散列值拿來和随資料傳輸的散列值比較。如果兩個值相同,說明傳輸的資料完整無誤、沒有被竄改過(前提是散列值沒有被竄改),進而可以放心使用。
如客戶往我們資料中心同步一個檔案,該檔案使用MD5校驗,那麼客戶在發送檔案的同時會再發一個存有校驗碼的檔案,我們拿到該檔案後做MD5運算,得到的計算結果與客戶發送的校驗碼相比較,如果一緻則認為客戶發送的檔案沒有出錯,否則認為檔案出錯需要重新發送。
另外值得注意的是,檔案傳輸過程中,還有一些粘包問題,這個問題,我會單獨列出部落格來整理
敬請期待
同時由于個人時間限制,上傳檔案暫時移到明天(需要注意的是,這裡的檔案指的是,txt,jpg,png等格式,而不是檔案夾,關于檔案夾,後面我們會将它放到一個web上下載下傳,這裡不做處理)
首先老規矩:先建立
server = socket.socket()
server.bind(('localhost',6666))
server.listen()
while True:
conn, addr = server.accept()
print("new addr:",addr)
這個是相當格式化的部分,建立服務端,與用戶端進行連接配接,并列印用戶端的位址
client = socket.socket()
client.connect(('localhost', 6666))
同理,這是用戶端
cmd = input(">>>:").strip()
if len(cmd)==0:
continue
if cmd.startswith("get"):
filename = cmd.split()[1] #擷取檔案名
client.send(cmd.encode("utf-8"))#用戶端把要下載下傳的檔案資訊,交給服務端
這個上節已經分享到過,這裡不作解釋
這個是用戶端要求你所輸入的檔案來源,輸入格式是
get C:\Users\Public\Pictures\938876-20160611152927293-1786781422.png
有個同學,會有疑問cmd.split()[1],為什麼會是一哇,不能是二或三嗎
C:\Users\Public\Pictures\938876-20160611152927293-1786781422.png
注意,這裡他的前面有一個空格,是以,可以提取後面的一位
while True:
data = conn.recv(1024)
if not data:
print("用戶端已斷開。。。")
break
cmd, filename = data.decode().split()#對資訊進行解碼,并除去空格,轉化為兩個字元串
print(filename)
服務端進行接受,其中 filename 為你的檔案來源
if os.path.isfile(filename):
此步是為了判斷,檔案是否存在,如果存在,可以繼續進行
f = open(filename,"rb")#打開檔案
file_size = os.stat(filename).st_size
conn.send(str(file_size).encode("utf-8")) #發送檔案大小
發送檔案大小
用戶端要開始接受檔案大小了:
server_resp_size = client.recv(1024) #接收檔案總的大小
file_total_size = int(server_resp_size.decode())
print("file size:", server_resp_size)#将檔案大小進行列印
大家學到此處,可還有疑問?如果有疑問,歡迎咨詢.
上面第一階段,已經完成了,接下來就是正式的檔案下載下傳階段了
client.send(b"ready to recv file...")#用戶端,發消息,我要開始接收檔案了
conn.recv(1024) #服務端,接收消息
服務端 for line in f:
m.update(line)
conn.send(line)
開始周遊檔案,更新消息
用戶端;f = open(filename+".new","wb"),建立一個以new格式的檔案,用來接收服務
端發來的消息
用戶端開始接受檔案
while recv_size < file_total_size:#目的是為了防止黏包問題出現
if file_total_size - recv_size > 1024: #判斷最後一次,之前接收大小設定為1024
size = 1024
else: #最後一次不足1024,則隻接收檔案剩餘的部分,不包含MD5
size = file_total_size - recv_size
print("the last size:",size)
data = client.recv(size)
recv_size += len(data)
f.write(data)
服務端大緻思路:
<a href="https://s1.51cto.com/oss/201711/15/09f753100746e0a921c363a050d26e62.png-wh_500x0-wm_3-wmp_4-s_3391020654.png" target="_blank"></a>
是以總的服務端代碼
import os,socket,hashlib
server.bind(('localhost',9999))
conn, addr = server.accept()
print("new addr:",addr)
while True:
data = conn.recv(1024)
if not data:
print("用戶端已斷開。。。")
break
cmd, filename = data.decode().split()
print(filename)
if os.path.isfile(filename):
f = open(filename,"rb")
m = hashlib.md5()
file_size = os.stat(filename).st_size
conn.send(str(file_size).encode("utf-8")) #發送檔案大小
conn.recv(1024) #等待回複
for line in f:
m.update(line)
conn.send(line)
print("file md5:",m.hexdigest())
f.close()
conn.send(m.hexdigest().encode("utf-8")) #發送MD5,與上面的“conn.send(line)”可能出現粘包
print("send done...")
server.close()
<a href="https://s5.51cto.com/oss/201711/15/69536ea6ea36d8d8d2b18756fdbd86f0.png-wh_500x0-wm_3-wmp_4-s_1452155190.png" target="_blank"></a>
用戶端代碼:
import socket,hashlib
client.connect(('localhost', 9999))
cmd = input(">>>:").strip()
if len(cmd)==0:
continue
if cmd.startswith("get"):
filename = cmd.split()[1] #擷取檔案名
client.send(cmd.encode("utf-8"))
server_resp_size = client.recv(1024) #接收檔案總的大小
file_total_size = int(server_resp_size.decode())
print("file size:", server_resp_size)
client.send(b"ready to recv file...")
f = open(filename+".new","wb")
recv_size = 0
m = hashlib.md5()
while recv_size < file_total_size:
if file_total_size - recv_size > 1024: #判斷最後一次,之前接收大小設定為1024
size = 1024
else: #最後一次不足1024,則隻接收檔案剩餘的部分,不包含MD5
size = file_total_size - recv_size
print("the last size:",size)
data = client.recv(size)
recv_size += len(data)
f.write(data)
m.update(data)
else:
client_md5 = m.hexdigest()
print("recv done...")
print("total size:", file_total_size, "had been received:", recv_size)
server_md5 = client.recv(1024)
print("server md5:", client_md5, "server md5:", server_md5.decode())
client.close()
<a href="https://s4.51cto.com/oss/201711/15/5507e250234ea7fb1723ef7bb92496f0.png-wh_500x0-wm_3-wmp_4-s_3346951819.png" target="_blank"></a>
<a href="https://s4.51cto.com/oss/201711/15/af0b77968ab298adf36621e83122f800.png-wh_500x0-wm_3-wmp_4-s_3827459950.png" target="_blank"></a>
<a href="https://s4.51cto.com/oss/201711/15/8c27a4f62e0f537e6a2444f7fc8992d1.png-wh_500x0-wm_3-wmp_4-s_2928388090.png" target="_blank"></a>
本文轉自眉間雪 51CTO部落格,原文連結:http://blog.51cto.com/13348847/1982209,如需轉載請自行聯系原作者