#在網絡上面傳輸的數據叫數據包,數據包裏面的數據叫報文,報文都有報頭。
#報頭能夠包含文件路徑、文件大小、文件名稱等等。
#當數據比較長,一次性發送會報錯,須要分屢次發送。
#client端上傳數據到server端,server端下載數據:
#client端:
import socket
import os
import json
import struct
sk = socket.socket()
sk.connect(('127.0.0.1',9008))
buffer = 4096
#定製報頭
head = {'directory':r'D:\python教學視頻\day32', #字符串前面加r,表示原生字符串,反斜槓\不起轉義做用。
'name':r'06 python fullstack s9day32 struct模塊定製報頭ftp實踐.mp4',
'size':None}
file_path = os.path.join(head['directory'],head['name']) #文件路徑=目錄+名稱
print(file_path)#D:\python教學視頻\day32\06 python fullstack s9day32 struct模塊定製報頭ftp實踐.mp4
filesize = os.path.getsize(file_path) #文件大小,經過文件路徑獲得文件大小。
print(filesize)
head['size'] = filesize #把字典的值None修改成filesize。
#報頭是字典,先轉爲str,再轉爲bytes才能經過網絡發送:
json_head = json.dumps(head)#字典轉爲字符串
bytes_head = json_head.encode('utf-8')#字符串轉爲字節bytes
#發送含有報頭長度的包和報頭:
pack_len = struct.pack('i',len(bytes_head))#打包bytes類型的報頭的長度。
sk.send(pack_len) #先發含有報頭長度的包
sk.send(bytes_head) #再發bytes類型的報頭
#發送報文:當數據比較長,一次性發送會報錯,須要分屢次發送。
with open(file_path,'rb') as f:
while filesize > 0:
if filesize > buffer:
content = f.read(buffer) #每次讀取4096個字節的內容,而後發送過去。
sk.send(content)
filesize -= buffer
else:
content = f.read(filesize)
sk.send(content)
break
sk.close()
#server端:
import socket
import struct
import json
buffer = 4096
sk = socket.socket()
sk.bind(('127.0.0.1',9008))
sk.listen()
conn,addr = sk.accept()
pack = conn.recv(4) #接收含有報頭長度的包,接收4個字節的包。
unpack = struct.unpack('i',pack) #解包
json_head = conn.recv(unpack[0]).decode('utf-8') #接收報頭長度大小的內容,解碼爲str
head = json.loads(json_head) #str轉爲字典
filesize = head['size']
with open('教學視頻.mp4','wb') as f: #在跟本py文件同一目錄下建立 教學視頻.mp4 文件。
while filesize > 0:
if filesize >= buffer:
content = conn.recv(buffer)
f.write(content)
filesize -= buffer
else:
content = conn.recv(filesize)
f.write(content)
break
conn.close()
sk.close()