05,tcp 應用 :文件的上傳

1 ,文件上傳 : 思路

  1. 服務端開啓,準備接收文件
  2. 文件內容分三部分
    1 ,報文長度
    2 ,報文
    3 ,文件內容
  3. 解析 :
    1 ,先讀取 4 個字節,得到長度 n ( 固定用 4 字節來存儲長度這個數字 )
    2 ,再讀取 n 個字節,得到報文
    3 ,解析報文,得到文件長度 m
    4 ,寫一個 while 循環,讀取長度爲 m 的文件

2 ,文件上傳 : 服務端

# Author:SFL

import socket
import struct
import json

sk = socket.socket()
sk.bind(('127.0.0.1', 8888))  # 綁定ip地址和端口
sk.listen()  # 開啓監聽

buffer = 1024  # 緩衝區大小
conn, addr = sk.accept()    # 等着輸入

# 先接收報頭的長度 ( 我們規定了前 4 位,代表報頭的長度 )
head_len = conn.recv(4)
head_len = struct.unpack('i', head_len)[0]  # 將報頭長度解包出來
# 再接收報頭
json_head = conn.recv(head_len).decode('utf-8')  # 拿到的是bytes類型的數據,要進行轉碼
head = json.loads(json_head)  # 拿到原本的報頭
# 從報頭中,拿到文件的長度
file_size = head['filesize']

# 打開文件,追加模式,字節模式,將字節流輸入到這裏面
with open("2.jpg", 'ab') as f:
    # 文件長度
    while file_size:
        if file_size >= buffer:  # 判斷剩餘文件的大小是否超過buffer
            # 緩衝區有多大,每次就接收多少內容
            content = conn.recv(buffer)
            f.write(content)
            file_size -= buffer
        else:
            # 最後,剩餘內容小於緩衝區的大小,就接收到文件剩下的那麼多的內容
            content = conn.recv(file_size)
            f.write(content)
            file_size = 0
            break
conn.close()
sk.close()

3 ,文件上傳 : 客戶端

# Author:SFL
import socket
import os
import json
import struct

sk = socket.socket()
sk.connect(('127.0.0.1', 8888))  # 與服務器建立連接

buffer = 1024 # 緩衝區大小
# 定製我們的報頭,這裏的報頭不是唯一的,你可以根據你的想法去更改
head = {'filesize': None}
file_name = "1.jpg"
# 計算文件的大小
filesize = os.path.getsize(file_name)
head['filesize'] = filesize
json_head = json.dumps(head)  # 利用json將字典轉成字符串
bytes_head = json_head.encode('utf-8')  # 字符串轉bytes
# 計算head長度
head_len = len(bytes_head)  # 報頭的長度
# 利用struct將int類型的數據打包成4個字節的byte,所以服務器端接受這個長度的時候可以固定緩衝區大小爲4
pack_len = struct.pack('i', head_len)
# 先將報頭長度發出去
sk.send(pack_len)
# 再發送bytes類型的報頭
sk.send(bytes_head)
# 最後,上傳文件
with open(file_name, 'rb') as f:
    while filesize:
        if filesize >= buffer:
            content = f.read(buffer)  # 每次讀取buffer字節大小內容
            filesize -= buffer
            sk.send(content)  # 發送讀取的內容
        else:
            content = f.read(filesize)
            sk.send(content)
            filesize = 0
            break
sk.close()

4 ,使用 :

  1. 先開服務端
  2. 再開客戶端
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章