網路程式設計基礎【day09】:socket解決粘包問題之MD5(八)
阿新 • • 發佈:2018-11-02
本節內容
1、概述
2、程式碼實現
一、概述
上一篇部落格講到的用MD5來校驗還是用的之前解決粘包的方法,就是客戶端傳送一個請求,等待服務端的確認的這樣的一個笨方法。下面我們用另外一種方法:就是客戶端已經知道可接收多少資料了,既然客戶端已經知道接收多少資料了,那麼客戶端在接收資料的時候,正好接收已經知道的資料,不就ok了嗎?就是說我迴圈了正好是收到已經知道的那些資料。比如:我要發5M的資料,我正好收到5M的資料,然後就不往下再收了,因為它有可能跟MD5值黏在一塊了,本來說是發5M檔案,結果你發了5.1M,那麼客戶端正好收5M的話,那客戶端的0.1M是不是就不收了,不收了之後我就把客戶端把檔案存下來,再來recive一下,下面recive的正好是0.1M。
二、程式碼實現
說明:其實我們在接收檔案時,只有最後一次才會超過接收大小,所以我們從這裡下手
2.1、服務端程式碼
說明:生成md5物件->傳送的資料生成MD5值->傳送MD5 值
①程式碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
import
hashlib
import
socket,os
server
=
socket.socket()
server.bind((
"localhost"
,
9999 ))
server.listen()
while
True
:
conn,addr
=
server.accept()
print
(
"new conn:"
,addr)
while
True
:
print
(
"等待新指令"
)
data
=
conn.recv(
1024
)
if
not
data:
print
(
"客戶端已斷開"
)
break
cmd,filename
=
data.decode().split()
print
(filename)
if
os.path.isfile(filename):
m
=
hashlib.md5()
#生成MD5的物件
with
open
(filename,
"rb"
) as f:
file_size
=
os.stat(filename).st_size
conn.send(
str
(file_size).encode() )
#send file size
conn.recv(
1024
)
for
line
in
f:
m.update(line)
#計算md5值
conn.send(line)
#傳送資料至客戶端
print
(
"file md5"
,m.hexdigest())
conn.send(m.hexdigest().encode())
#生成MD5值並且傳送給客戶端
print
(
"send done"
)
server.close()
|
②程式碼改動
2.2、客戶端
說明:檔案大小-接收大小是否大於1024 ->獲取size值->recive(size)->下面再次recive時就是MD5值了
①程式碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
import
socket,hashlib
client
=
socket.socket()
client.connect((
"localhost"
,
9999
))
while
True
:
cmd
=
input
(
">>>:"
).strip()
if
len
(cmd)
=
=
0
:
continue
if
cmd.startswith(
"get"
):
client.send(cmd.encode())
server_respose
=
client.recv(
1024
)
print
(
"server response:"
,server_respose)
client.send(
"ready to recv file"
.encode())
file_total_size
=
int
(server_respose.decode())
revived_size
=
0
filename
=
cmd.split()[
1
]
m
=
hashlib.md5()
#生成MD5物件
with
open
(filename
+
".new"
,
"wb"
) as f:
while
revived_size < file_total_size:
if
file_total_size
-
revived_size >
1024
:
#要收不止一次
size
=
1024
else
:
#最後一次,剩多少收多少
size
=
file_total_size
-
revived_size
print
(
"last receive:"
,size)
data
=
client.recv(size)
revived_size
+
=
len
(data)
m.update(data)
#計算資料接收的MD5值
f.write(data)
else
:
print
(file_total_size,revived_size)
new_file_md5
=
m.hexdigest()
#生成接收資料的MD5值16進位制形式
server_file_md5
=
client.recv(
1024
)
#接收客戶端的MD5值
print
(
"server file md5:"
,server_file_md5.decode())
print
(
"client file md5:"
,new_file_md5)
client.close()
|
②程式碼改動