最簡單的FTP上次文件
# TCP服務端_server.py import socket import struct sk = socket.socket() # 創建socket對象 sk.bind(("127.0.0.1", 6666)) # 綁定IP和端口號 sk.listen() # 開啟監聽 print("開啟監聽!") conn, address = sk.accept() # 等待客戶端連接 阻塞 print("客戶端連接成功!") file_size = struct.unpack("i", conn.recv(4))[0] f = open("upload/flower.jpg", "wb") while file_size > 0: msg = conn.recv(1024) f.write(msg) file_size -= len(msg) conn.close() sk.close()
# TCP客戶端_client.py import socket import struct import os sk = socket.socket() # 創建socket對象 sk.connect(("127.0.0.1", 6666)) # 連接服務端 file_name = "timg.jpg" file_size = os.path.getsize(file_name) sk.send(struct.pack("i", file_size)) with open(file_name, "rb") as f: for line in f: sk.send(line) print(f"文件{file_name}上傳完成!") sk.close()
注意:
先執行服務端,再執行客戶端,最后會在upload文件夾下看到你上傳的文件。
將文件大小和文件名放入字典中,先發送字典轉字符串的字節長度,再發送字典轉字符串后的字節
# TCP服務端_server.py import socket import struct import json sk = socket.socket() # 創建socket對象 sk.bind(("127.0.0.1", 6666)) # 綁定IP和端口號 sk.listen() # 開啟監聽 print("開啟監聽!") conn, address = sk.accept() # 等待客戶端連接 阻塞 print("客戶端連接成功!") dic_json_len = struct.unpack("i", conn.recv(4))[0] # 先接收json字符串長度 dic_json = conn.recv(dic_json_len).decode("utf-8") # 接收json字符串 dic = json.loads(dic_json) # 轉化為字典 file_size = dic.get("file_size") # 文件大小 file_name = dic.get("file_name") # 文件名 f = open(f"upload/{file_name}", "wb") # 以rb模式寫文件 while file_size > 0: # 循環接收文件內容 msg = conn.recv(1024) f.write(msg) file_size -= len(msg) conn.close() sk.close()
# TCP客戶端_client.py import socket import struct import json import os sk = socket.socket() # 創建socket對象 sk.connect(("127.0.0.1", 6666)) # 連接服務端 file_name = "timg.jpg" # 文件名 file_size = os.path.getsize(file_name) # 文件大小 dic = {"file_name": file_name, "file_size": file_size} # 將文件名和文件大小放入字典中 dic_json_str = json.dumps(dic) # 將字典轉化為json字符串 dic_bs = dic_json_str.encode("utf-8") # 對json字符串進行編碼,轉化為字節 sk.send(struct.pack("i", len(dic_bs))) # 先發送json字符串的長度 sk.send(dic_bs) # 在發送json字節 with open(file_name, "rb") as f: # 以rb模式讀取要上傳的文件 for line in f: sk.send(line) # 逐行發送文件內容 print(f"文件{file_name}上傳完成!") sk.close()
注意:
先執行服務端,后執行客戶端,最后會在upload文件夾看到你上傳的同名文件。
即便是視頻文件,也是可以按行來讀取的,也可以readline,也可以for循環,但是讀取出來的數據大小就不固定了,影響效率,有可能讀的比較小,
也可能很大,像視頻文件一般都是一行的二進制字節流。
所有我們可以用read,設定一個一次讀取內容的大小,一邊讀一邊發,一邊收一邊寫。
-------------------------------------ftp_server.py-------------------------------------
# coding:utf-8 import json import socket import struct server = socket.socket() ip_port = ("127.0.0.1", 8001) buffer = 1024 server.bind(ip_port) server.listen(5) conn, addr = server.accept() header_len = conn.recv(4) # 接收報頭長度 header_bytes = conn.recv(struct.unpack('i', header_len)[0]) # 接收報頭 header = json.loads(header_bytes.decode("utf-8")) # 報頭解碼->反序列化 file_size = header['filesize'] # 文件的大小 print(file_size, buffer) with open(header['filename'], "wb") as f: while file_size: if file_size >= buffer: f.write(conn.recv(buffer)) file_size -= buffer print(file_size, buffer) else: f.write(conn.recv(buffer)) print(file_size, buffer) break conn.close() server.close()
-------------------------------------ftp_client.py-------------------------------------
# coding:utf-8 import os import json import struct import socket client = socket.socket() ip_port = ("127.0.0.1", 8001) client.connect(ip_port) buffer = 1024 header = { # 報頭為dict類型 "filename": "day08.md", "filepath": r"F:\2019老男孩周末26期\day08\課下練習", "filesize": 0, } file_path = os.path.join(header['filepath'], header['filename']) file_size = os.path.getsize(file_path) header['filesize'] = file_size header_json = json.dumps(header) # 報頭序列化為json字符串 header_bytes = header_json.encode("utf-8") # 報頭編碼為bytes類型 client.send(struct.pack('i', len(header_bytes))) # 發送4個字節的報頭大小 client.send(header_bytes) # 發送報頭 print(file_size, buffer) with open(file_path, "rb") as f: while file_size: if file_size >= buffer: client.send(f.read(buffer)) file_size -= buffer print(file_size, buffer, "第一次或中間的") else: client.send(f.read(buffer)) print(file_size, buffer, "最后一次") break client.close()