简单版
服务端
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()