主要内容 :
1 . struct 模块 : 可以把一种数据类型, 如数字,转换成固定长度的bytes.
-2147483648 ------ 2147483648 4bytes
import struct a = 123 abs_len_by = struct.pack('i', a) print(abs_len_by,len(abs_len_by)) #b'{x00x00x00' 4 ret = struct.unpack('i',abs_len_by) print(ret) #(123,)返回值是一个元祖
2 . 大文件的传输
a: 版本一 : 解决黏包问题的大文件传输
服务器端代码 :
import socket import json import struct sk = socket.socket() sk.bind(("127.0.0.1",8091)) sk.listen() conn, addr = sk.accept() b_len_dic = conn.recv(4) len_dic = struct.unpack('i', b_len_dic)[0]# 获取到int类型字典的长度, # unpack得到的是一个元组,要取下标为0的位置 str_dic = conn.recv(len_dic).decode('utf-8') dic = json.loads(str_dic) if dic["opt"] == "upload": filename = "1" + dic["filename"] with open(filename, "ab") as f: while dic['filesize']: content = conn.recv(1024) f.write(content) dic['filesize'] -= len(content) elif dic["opt"] == "download": pass conn.close() sk.close()
客户端代码:
import socket import os import json import struct sk = socket.socket() sk.connect(("127.0.0.1", 8091)) menu = {"1": "upload", "2": "download"} for k, v in menu.items(): print(k, v) num = input("请输入功能选项:") if num == "1": dic = {"opt": menu.get(num), "filename": None, "filesize": None} file_path = input("请输入一个绝对路径:")# 文件的绝对路径 # E:Python S14day32实现大文件的传输11.mp4 filename = os.path.basename(file_path)# 文件名字 filesize = os.path.getsize(file_path)# 获取用户输入的路径中文件的大小 dic["filename"] = filename dic["filesize"] = filesize str_dic = json.dumps(dic) len_dic = len(str_dic)# 获取到字典的长度,是一个int类型的数据 46 146 b_len_dic = struct.pack('i',len_dic)# 用一个4bytes的数据表示字典的长度 sk.send(b_len_dic + str_dic.encode("utf-8"))# 将bytes类型的字典的长度 + bytes类型的字典的内容,一起发送给服务器 with open(file_path, "rb") as f: while filesize: content = f.read(1024) sk.send(content) filesize -= len(content) elif num == "2": pass
b : 版本二: 大文件的传输:
服务器端的代码:
import socket import json sk = socket.socket() sk.bind(("127.0.0.1",8001)) sk.listen() conn,addr = sk.accept() str_dic = conn.recv(100).decode("utf-8") conn.send(b'ok') # str_dic = {"opt":menu.get(num),"filename":None,"filesize":None} dic = json.loads(str_dic) if dic["opt"] == "upload": filename = "1"+ dic["filename"] with open(filename,"ab") as f: while dic['filesize']: content = conn.recv(1024) f.write(content) dic['filesize'] -= len(content) elif dic["opt"] == "download": pass conn.close() sk.close()
客户端的代码:
import socket import os import json sk = socket.socket() sk.connect(("127.0.0.1",8001)) menu = {"1":"upload","2":"download"} for k,v in menu.items(): print(k,v) num = input("请输入功能选项:") if num == "1": dic = {"opt":menu.get(num),"filename":None,"filesize":None} file_path = input("请输入一个绝对路径:")# 文件的绝对路径 filename = os.path.basename(file_path)# 文件名字 filesize = os.path.getsize(file_path)# 获取用户输入的路径中文件的大小 dic["filename"] = filename dic["filesize"] = filesize str_dic = json.dumps(dic) sk.send(str_dic.encode("utf-8"))# 将被填充完成的字典先发送给服务器 sk.recv(1024)# 为什么要有一个recv? # 因为上边send字典时,如果程序执行过快,可能会马上执行到下边的send(content) # 此时有可能会发生粘包,所以在此中间加一个recv,为了避免粘包 with open(file_path,"rb") as f: while filesize: content = f.read(1024) sk.send(content) filesize -= len(content) elif num == "2": pass
c : 版本三 : 小文件的传输
服务器端的代码:
import socket import json sk = socket.socket() sk.bind(("127.0.0.1",8001)) sk.listen() conn,addr = sk.accept() str_dic = conn.recv(9090).decode("utf-8") dic = json.loads(str_dic) if dic["opt"] == "upload": filename = "1"+ dic["filename"] with open(filename,"w",encoding="utf-8") as f: f.write(dic["content"]) elif dic["opt"] == "download": pass conn.close() sk.close()
客户端的代码:
import socket import os import json sk = socket.socket() sk.connect(("127.0.0.1",8001)) menu = {"1":"upload","2":"download"} for k,v in menu.items(): print(k,v) num = input("请输入功能选项:") if num == "1": dic = {"opt":menu.get(num),"filename":None,"content":None} file_path = input("请输入一个绝对路径:") filename = os.path.basename(file_path) with open(file_path,"r",encoding="utf-8") as f: content = f.read() dic["filename"] = filename dic["content"] = content str_dic = json.dumps(dic) sk.send(str_dic.encode("utf-8")) elif num == "2": pass
3 . 切换目录
用户输入一个绝对路径, 以此路径为基础(此时服务器应该返回这个目录下的所有文件及文件夹) 如果用户继续输入..服务器要返回上一层的所有文件及文件夹 如果用户输入的是cd 后边一定要求用户继续输入一个当前目录下的文件夹的名字.此时 服务器需要给用户返回该文件夹下的所有文件及文件夹
服务器端代码:
import socket import os sk = socket.socket() sk.bind(('127.0.0.1', 9080)) sk.listen() conn, addr = sk.accept() abs_path = conn.recv(1024).decode('utf-8') dir = os.listdir(abs_path) str = '--'.join(dir) conn.send(str.encode('utf-8')) while 1: cmd = conn.recv(1024).decode('utf-8') if cmd == '..': file_path = os.path.dirname(abs_path) dir = os.listdir(file_path) str = '--'.join(dir) abs_path = file_path conn.send(str.encode('utf-8')) else: print(cmd) file_name = cmd.split(':')[1] current_path = abs_path +'/' +file_name if os.path.isdir(current_path): file_lst = os.listdir(current_path) flie_str = '--'.join(file_lst) abs_path = current_path conn.send(flie_str.encode('utf-8')) else: conn.send(r'bushiwenjian') conn.close() sk.close()
客户端代码:
import socket sk = socket.socket() sk.connect(('127.0.0.1',9080)) abs_path = input('请输入一个绝对路径:') sk.send(abs_path.encode('utf-8')) str = sk.recv(1024).decode('utf-8') dir = str.split('--') print(dir) while 1: cmd = input('请用户输入命令:') if cmd == '..': sk.send(cmd.encode('utf-8')) str = sk.recv(1024).decode('utf-8') dir = str.split('--') print(dir) if cmd == 'cd': file_name = input('请用户输入一个文件夹的名字>>>') sk.send((cmd + ':'+file_name).encode('utf-8')) current_dir = sk.recv(1024).decode('utf-8') print(current_dir.split('--')) sk.close()