在这里我实现的是客户端上传文件,服务器接收文件,如果要实现客户端从服务器上下载文件的话,直接将代码反过来即可。废话不多说,下面直接上代码吧。
下面是服务器端的代码
import socket
import struct
import json
sk = socket.socket()
sk.bind(('127.0.0.1', 8888)) # 绑定ip地址和端口
sk.listen() # 开启监听
buffer = 1024 # 缓冲区大小,这里好像因为windows的系统的原因,这个接收的缓冲区不能太大
conn, addr = sk.accept()
# 先接收报头的长度
head_len = conn.recv(4)
head_len = struct.unpack('i', head_len)[0] # 将报头长度解包出来
# 再接收报头
json_head = conn.recv(head_len).decode('utf-8') # 拿到的是bytes类型的数据,要进行转码
head = json.loads(json_head) # 拿到原本的报头
file_size = head['filesize']
with open(head['filename'], 'ab') as f:
print(file_size)
while file_size:
if file_size >= buffer: # 判断剩余文件的大小是否超过buffer
content = conn.recv(buffer)
f.write(content)
file_size -= buffer
else:
content = conn.recv(file_size)
f.write(content)
file_size = 0
break
conn.close()
sk.close()
下面是客户端的代码
import socket
import os
import json
import struct
sk = socket.socket()
sk.connect(('127.0.0.1', 8888)) # 与服务器建立连接
buffer = 1024
# 定制我们的报头,这里的报头不是唯一的,你可以根据你的想法去更改
head = {'filepath': r'你的文件路径',
'filename': r'你要传的文件名',
'filesize': None}
file_path = os.path.join(head['filepath'], head['filename'])
# 计算文件的大小
filesize = os.path.getsize(os.path.join(head['filepath'], head['filename']))
head['filesize'] = filesize
json_head = json.dumps(head) # 利用json将字典转成字符串
bytes_head = json_head.encode('utf-8') # 字符串转bytes
# 计算head长度
head_len = len(bytes_head) # 报头的长度
# 利用struct将int类型的数据打包成4个字节的byte,所以服务器端接受这个长度的时候可以固定缓冲区大小为4
pack_len = struct.pack('i', head_len)
# 先将报头长度发出去
sk.send(pack_len)
# 再发送bytes类型的报头
sk.send(bytes_head)
with open(file_path, 'rb') as f:
while filesize:
print(filesize)
if filesize >= buffer:
content = f.read(buffer) # 每次读取buffer字节大小内容
filesize -= buffer
sk.send(content) # 发送读取的内容
else:
content = f.read(filesize)
sk.send(content)
filesize = 0
break
sk.close()
在这个上传、下载文件的实验中,发现了一个现象,就是buffer基本不能超过1024字节大小,,如果超过1024的大小就会报错,这可能与windows操作系统有关,可能是由于读写不同步造成的。