python tcp 服務器端發送文件+客戶端接受文件


該程序基於tcp協議,實現服務端向客戶端傳輸文件的功能。

當服務端發送的文件過大時,客戶端無法正常接受,造成黏包現象。解決的方案是,每次發送文件時,告訴客戶端服務器要發送文件的大小,同時將文件按指定大小(m)拆分開發送。客戶端在接受到文件大小后,按指定大小(n)進行接受。m最好和n相等,感興趣的話可以自己試試看,m和n的之間存在什么關系。

這里用struct模塊優化代碼。len_a = struct.pack('i', len(a))將a的值長度計算出來,並轉化成4位的bytes類型; struct.unpack('i',len)將bytes類型的len轉化成int型的數字,並放入到元組中;所有b= struct.unpack('i',len).[0]中,b是變量a的值長度,即len(a)=b。關於struct的使用,詳細使用看【】注釋對應的行。當然,我們也可以通過其len函數來獲取a值長度,然后再轉化成bytes類型,再解碼。

服務端的代碼

 

 1 import json
 2 import socket
 3 import struct
 4 import os
 5 server = socket.socket()
 6 server.bind(('127.0.0.1',9002))
 7 server.listen()
 8 
 9 conn,addr = server.accept()
10 #發送文件的信息:文件名、文件大小、文件路徑
11 f_head = {'f_name': r'xxxx2019.doc',                  #文件名稱(r表示字符串不發生轉換)
12           'f_size': None,                              #文件大小(未賦值)
13           'f_path': r'C:\Users\Apple\Desktop\學習\s1' #文件存儲位置
14           }
15 fPath = os.path.join(f_head['f_path'],f_head['f_name']) #文件路徑(位置+名字)
16 fSize = os.path.getsize(fPath)                          #文件大小
17 f_head['f_size'] = fSize                                #給字典f_head的f_size賦值
18 j_head = json.dumps(f_head)                             #字典f_head轉換成字符串
19 b_head = j_head.encode('utf-8')                         #字符串(f_head)轉bytes
20 head_len = struct.pack('i', len(b_head))                #【獲取(f_head)bytes類型長度】
21 conn.send(head_len)                                     #發送f_head長度到客戶端
22 conn.send(b_head)                                       #發送f_head內容到客戶端
23 num = 1024 #m
24 
25 #讀取fpath路徑下的文件,拆分文件並發送;至所有文件發送完畢跳出循環26 with open(fPath,'rb') as f:
27     while fSize > num:
28         conn.send(f.read(num))
29         fSize = fSize - num
30     conn.send(f.read(fSize))
31 
32 conn.close()
33 server.close()

 

 

 

客戶端的代碼

 

 1 import json
 2 import socket
 3 import struct
 4 
 5 client = socket.socket()
 6 client.connect(('127.0.0.1', 9002))
 7 
 8 num = 1024 #n
 9 head_len = struct.unpack('i', client.recv(4))[0]  #【接受服務端發來的f_head(bytes類型)的大小,並轉化成int類型】
10 j_head = client.recv(head_len).decode('utf-8')    #接受服務端發來的f_head,並解碼得到字符串
11 head = json.loads(j_head)                         #講字符串類型的f_head,轉換為字典類型
12 fSize = head['f_size']                            #獲取head的f_size值(即服務端f_head的f_size值)
13 
14 #分部接受來自服務端的文件,並寫入;至所有文件接受完畢結束循環。15 with open(head['f_name'],'wb') as f:
16     while fSize > num:
17         msg = client.recv(num)
18         f.write(msg)
19         fSize = fSize - num
20     msg = client.recv(fSize)
21     f.write(msg)
22 
23 client.close()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM