#文件的上传和下载:
#自定义一个字典,让用户选择功能(上传/下载)。将要上传的文件路径传入,找到文件名,打开文件,计算文件大小,
#将功能、文件名、文件大小定义成一个字典,通过stuct模块和json模块固定字典的长度为4并序列化,以便防止发送
#时与后面要发送的文件内容出现黏包现象。通过循环将文件按照固定的大小(1024)分次发送到服务端。服务端也根据收到
#的文件大小来分次接收。
#struct模块
# import struct
# #
# r = struct.pack('i',10) #将10变成一个固定的长度4的字符串
# print(len(r))
# print(r)
# print(struct.unpack('i',r))#解开,得到的是一个元祖形式,原数值在元祖的第0个元素。
# import json
# dic = {'a': '1'}
# r = json.dumps(dic)
# print(json.loads(r))
server:
import socket
import struct
import json
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen(5)
conn , addr = sk.accept()
r = conn.recv(4) #接收从客户端处已经被struct模块将原字典长度转换成固定长度的bytes(长度为4)
len_dic = struct.unpack('i',r)[0]#将这个bytes解开,变成一个元祖,要的是第一个元素-->原字典的长度。
# print(len_dic)
str_dic = conn.recv(len_dic).decode('utf-8')#根据原字典的长度来接收被序列化了字典
# print(str_dic)
str_dic = json.loads(str_dic)#将字典反序列化
if str_dic['opt'] == 'upload':
name = 'new_' + str_dic['name']#防止重名,加一个前缀。
with open(name,mode='wb') as f:#以bytes类型直接写进文件。
file_size = str_dic['file_size']#获取传入文件的大小。
while file_size:
content = conn.recv(1024)#分次接收。
f.write(content) #接收一次写入一次。
file_size -= len(content)#剩余的大小。
conn.close()#TCP协议两个套接字。
sk.close()
client:
import socket
import os
import json
import struct
sk = socket.socket()
sk.connect(('127.0.0.1',8080))
dic_c = {'1':'upload',
'2':'download'
} #定义一个供用户选择的字典
while 1:
num = input('请输入序号').strip()
if num == '1':
for k,v in dic_c.items():#将字典展示出来。
print(k,':',v)
path = input('请输入一个文件路径').strip()
name = os.path.basename(path) #获取文件名,传入服务端,写入文件用。
file_size = os.path.getsize(path)#获取文件大小,用来循环并分次传输。
dic = {'opt': dic_c[num],'name':name,'file_size':file_size}#将功能、文件名、大小作为字典传入服务端。
str_dic = json.dumps(dic) #将字典序列化,变成字符串,才能传输。
len_dic = len(str_dic) #计算序列化后的字典的长度。
r = struct.pack('i',len_dic)#通过序列号后的字典的长度将其变成长度为固定4位的bytes.
sk.send(r) #将固定后的bytes传入服务端。
sk.send(str_dic.encode('utf-8'))#另一端已经解出了序列化后字典的长度,发送即可。
with open(name,mode='rb') as f:#以bytes类型读取,就不用转码了。
while file_size:
content = f.read(1024)#分次读取
sk.send(content) #分次传输,直到传到没有为止。另一端也是与此同样来分次接收
file_size -= len(content)
break
sk.close()