檔案傳送
阿新 • • 發佈:2018-12-01
簡單版
服務端
import socket import subprocess import struct import json import os share_dir = r'F:\project\book\chapter6\檔案傳輸\簡單版本\server\share' phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # (如果機器中存在,重新用埠)應對端口占用報錯情況 phone.bind(("127.0.0.1", 9909)) # 127.0.0.1本地地址,埠範圍0-65535:其中0-1024給作業系統使用 phone.listen(5) # 5代表最大掛起連線數 print("starting...") while True: # 迴圈連結 conn, client = phone.accept() # conn套接字物件 while True: # 通訊迴圈 try: # 1、接收命令 (命令:執行系統命令) res = conn.recv(8096) # b'get a.txt # 2、解析命令,提取相應的命令引數 cmds = res.decode("utf-8").split() filename = cmds[1] # 3、以讀的方式開啟檔案,讀取檔案內容,傳送給客戶端 # 第一步:製作固定長度的報頭(import struct) header_dic = { "filename": filename, "md5": "xxdxxx", "file_size": os.path.getsize(r"%s/%s" % (share_dir, filename)) } header_json = json.dumps(header_dic) header_bytes = header_json.encode("utf-8") # 第二步:先發送報頭的長度 conn.send(struct.pack("i", len(header_bytes))) # 第三步:再發報頭 conn.send(header_bytes) # 第四步:再發送真實的資料 with open("%s/%s" % (share_dir, filename), "rb")as f: # conn.send(f.read()) # 如果檔案太大,會佔滿記憶體 for line in f: conn.send(line) except ConnectionRefusedError: break conn.close() phone.close()
客戶端
import socket import struct import json download_dir = r"F:\project\book\chapter6\檔案傳輸\簡單版本\client\download" phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) phone.connect(("127.0.0.1", 9909)) # phone相當於服務端的conn while True: # 1、發命令 cmd = input(">> ").strip() # get a.txt if not cmd: continue phone.send(cmd.encode("utf-8")) # 2、以寫的方式開啟一個新檔案,接收服務端發來的檔案的內容寫入客戶端的新檔案中 # 第一步:先收報頭的長度 header = phone.recv(4) header_size = struct.unpack("i", header)[0] # 第二步:再接收報頭資訊 header_bytes = phone.recv(header_size) # 第三步:從報頭中解析出對真實資料的描述資訊 header_json = header_bytes.decode("utf-8") header_dic = json.loads(header_json) print(header_dic) file_size = header_dic["file_size"] filename = header_dic["filename"] # 第四步:接受真實的資料 with open("%s/%s" % (download_dir, filename), "wb")as f: recv_size = 0 while recv_size < file_size: line = phone.recv(1024) f.write(line) recv_size += len(line) print("總大小:%s 已下載大小:%s" % (file_size, recv_size)) phone.close()
函式版
服務端
import socket import subprocess import struct import json import os share_dir = r'F:\project\book\chapter6\檔案傳輸\函式版本\server\share' def get(conn, cmds): filename = cmds[1] # 3、以讀的方式開啟檔案,讀取檔案內容,傳送給客戶端 # 第一步:製作固定長度的報頭(import struct) header_dic = { "filename": filename, "md5": "xxdxxx", "file_size": os.path.getsize(r"%s/%s" % (share_dir, filename)) } header_json = json.dumps(header_dic) header_bytes = header_json.encode("utf-8") # 第二步:先發送報頭的長度 conn.send(struct.pack("i", len(header_bytes))) # 第三步:再發報頭 conn.send(header_bytes) # 第四步:再發送真實的資料 with open("%s/%s" % (share_dir, filename), "rb")as f: # conn.send(f.read()) # 如果檔案太大,會佔滿記憶體 for line in f: conn.send(line) def put(conn, cmds): pass def run(): phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # (如果機器中存在,重新用埠)應對端口占用報錯情況 phone.bind(("127.0.0.1", 9909)) # 127.0.0.1本地地址,埠範圍0-65535:其中0-1024給作業系統使用 phone.listen(5) # 5代表最大掛起連線數 print("starting...") while True: # 迴圈連結 conn, client = phone.accept() # conn套接字物件 while True: # 通訊迴圈 try: # 1、接收命令 (命令:執行系統命令) res = conn.recv(8096) # b'get a.txt # 2、解析命令,提取相應的命令引數 cmds = res.decode("utf-8").split() if cmds[0] == "get": get(conn, cmds) elif cmds[0] == "put": put(conn, cmds) except ConnectionRefusedError: break conn.close() phone.close() if __name__ == "__main__": #如果是執行當前檔案的時候,這個條件成立,就執行。如果當前檔案被其他檔案當成模組匯入的時候,這個條件是不成立的,裡面的程式碼是不執行的 run()
客戶端
import socket import struct import json download_dir = r"F:\project\book\chapter6\檔案傳輸\函式版本\client\download" def get(phone, cmds): # 2、以寫的方式開啟一個新檔案,接收服務端發來的檔案的內容寫入客戶端的新檔案中 # 第一步:先收報頭的長度 header = phone.recv(4) header_size = struct.unpack("i", header)[0] # 第二步:再接收報頭資訊 header_bytes = phone.recv(header_size) # 第三步:從報頭中解析出對真實資料的描述資訊 header_json = header_bytes.decode("utf-8") header_dic = json.loads(header_json) print(header_dic) file_size = header_dic["file_size"] filename = header_dic["filename"] # 第四步:接受真實的資料 with open("%s/%s" % (download_dir, filename), "wb")as f: recv_size = 0 while recv_size < file_size: line = phone.recv(1024) f.write(line) recv_size += len(line) print("總大小:%s 已下載大小:%s" % (file_size, recv_size)) def put(phone, cmds): pass def run(): phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) phone.connect(("127.0.0.1", 9909)) # phone相當於服務端的conn while True: # 1、發命令 inp = input(">> ").strip() # get a.txt if not inp: continue phone.send(inp.encode("utf-8")) cmds = inp.split() # ["get","a.txt"] if cmds[0] == "get": get(phone, cmds) elif cmds[0] == "put": put(phone, cmds) phone.close() if __name__ == "__main__": # 如果是執行當前檔案的時候,這個條件成立,就執行。如果當前檔案被其他檔案當成模組匯入的時候,這個條件是不成立的,裡面的程式碼是不執行的 run()