基於之前解決粘包問題後,來實現檔案傳輸我們就不用subprocess模組了,要傳輸檔案首先需要開啟檔案以位元組的格式傳給對方,再讓對方解碼得到檔案。但在這之前,我們還需要制定一下規則,確定一下客戶端需要什麼檔案。他發給服務端的請求格式。比如:
cmd =
input
('>>:'
).strip(
)# get a.txt
ifnot cmd:
continue
phone.send(cmd.encode(
"gbk"
))
客戶端輸入『get a.txt』給服務端,服務端需要把這個訊息分成兩部分來解讀,第一部分是get,表示客戶端想要得到;第二部分是a.txt,指的是檔案的名稱。比如:
# 收命令
res = conn.recv(
8096
)# b'get a.txt'
# 解析命令、提取相應的命令引數
cmds = res.decode(
'gbk'
).split(
)# ['get','a.txt'] split變列**式
filename = cmds[
1]
這裡服務端用split把『get a.txt』分開變成列表。這樣我們就知道了客戶端需要什麼檔案,然後再自己庫中找到檔案傳送給客戶端。
最後,配合上之前的內容:
1、客戶端
import socket
import struct # 製作報頭的模組
import json # 轉換資料格式(序列化)
import os
share_dir =
''# 這裡是伺服器儲存資源的位址
phone = socket.socket(socket.af_inet, socket.sock_stream)
phone.bind(
('127.0.0.1'
,8848))
phone.listen(5)
while
true
: conn, client = phone.accept(
)while
true
:try
:# 收命令
res = conn.recv(
8096
)# b'get a.txt'
# 解析命令、提取相應的命令引數
cmds = res.decode(
'gbk'
).split(
)# ['get','a.txt'] split變列**式
filename = cmds[1]
# 已讀的方式開啟檔案,讀取檔案內容傳送給客戶端
# 第一步:製作固定長度的報頭
header_dic =
# 字典方便儲存資料
header_json = json.dumps(header_dic)
# 把字典轉換成js格式(字串型別)
header_bytes = header_json.encode(
'gbk'
)# 第二步:先傳送報頭的長度
conn.send(struct.pack(
'i',
len(header_bytes)))
# 第三步:再發報頭
conn.send(header_bytes)
# 第四步:傳送真實資料
with
open
('%s/%s'
%(share_dir, filename)
,'rb'
)as f:
for line in f:
# 這樣一行一行發比直接傳送f.read節省記憶體空間
conn.send(line)
except connectionreseterror as err:
break
conn.close(
)phone.close(
)
2、客戶端
import socket
import struct
import json
download_dir =
''# 這裡是客戶端存放資源的位址
phone = socket.socket(socket.af_inet, socket.sock_stream)
phone.connect(
('127.0.0.1'
,8848))
print
("------開始諮詢客服---------"
)while
true
:# 發命令
cmd =
input
('>>:'
).strip(
)# get a.txt
ifnot cmd:
continue
phone.send(cmd.encode(
"gbk"))
# 已寫的方式開啟乙個新檔案,接收伺服器發來的檔案的內容寫入客戶端的新檔案
# 第一步:先收取報頭的長度
obj = phone.recv(4)
header_size = struct.unpack(
'i', obj)[0
]# 第二步:再收報頭
header_bytes = phone.recv(header_size)
# 第三步:從報頭中間解析出對真是資料的描述資訊
header_json = header_bytes.decode(
'gbk'
) header_dic = json.loads(header_json)
print
(header_dic)
total_size = header_dic[
'file_size'
] filename = header_dic[
'filename'
]# 第三步:接受真實的資料
with
open
('%s/%s'
%(download_dir, filename)
,'wb'
)as f:
# 在自己的電腦中找乙個位址開啟乙個同型別的檔案準備接收資料
recv_size =
0while recv_size < total_size:
line = phone.recv(
1024
) f.write(line)
recv_size +=
len(line)
print(%
(total_size, recv_size)
)phone.close(
)
python實現檔案傳輸
我程式設計的時候,開了兩個python的shell,乙個做server,乙個做client 然後就直接在命令提示符下一行一行的編,感覺自己是在使用一套高階命令列,而不是在程式設計。server端 import socket sersock socket.socket socket.af inet,s...
Python實現TCP檔案傳輸
廢話少說,直接上 1 傳送端 2import socket,os 3from struct import pack45 def send file file name,file socket socket.socket 6try 7 f open file name,rb 8 size os.pat...
Python檔案傳輸
encode是編碼 例如 name.encode gb2312 表示將字串name以gb2312編碼。decode是解碼 例如 name.decode gb2312 表示將字串name以gb2312解碼。按行讀取txt裡的檔名,把檔案移到指定的路徑裡。coding utf 8 import thre...