python socket传输大文件的方法
日期: 2019-06-10 分类: 跨站数据测试 292次阅读
×××××××××××××方法一:
发送端
1、计算发送文件大小,然后结合文件的其他信息,组成文件头先发送一次。
2、发送文件数据时用sendall(),一次发送所有数据(好像是重复调用了send())
接收端
1、接收端根据接受文件的大小和recv_size计算要接收数据的次数,
2、然后把每次接收的数据连在一起
3、因为可能不是整除,最后要判断下最后一次具体接收多少字节数据(感觉也可以不用这样,直接接收)
1、计算文件大小
1、os.path.getsize(filepath)
2、os.stat(filepath).st_size
2、socket接收数据的操作的注意事项
因为下面的原因,我们要在接收端接收头文件时做一些处理,用来与数据文件区分
#服务器
import socket
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(("127.0.0.1",8000))
server.listen(3)
while True:
sock,adddr = server.accept()
data = sock.recv(1024)
print(data.decode("utf8")+"\n")
if(data.decode("utf8") == "111"):
print("dsfaf")
server.close()
sock.close()
#客户端
import socket
import json
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(("127.0.0.1",8000))
header_data = {
'file_size': 1000299,
}
client.send(json.dumps(header_data).encode("utf-8"))
client.send("ripo".encode("utf8"))
client.send("fasdf".encode("utf8"))
client.send("oiposfdpakf".encode("utf8"))
client.send("111".encode("utf8"))
client.close()
服务器输出结果
{"file_size": 1000299}ripofasdfoiposfdpakf111
可见虽然客户端是用多个send函数发送的,服务器采用1024大小的缓冲(sock.recv(1024))区,一次把所有数据的都接收了。这样就不能区分出我们先发送的文件头和文件内容了。
解决方案
1、使用send和recv隔离
在发送端第一次发送数据,也就是发送文件头信息的时候,接收端在接收后在给发送端发送一个数据,
然后发送端接收后(不必处理),相当于在发送文件头信息和文件信息之间加了一步,这样接收端就能区
分开了。
2、(推荐):使用struct计算头文件大小
使用struct库
1、首先在发送端和接收端约定一个fmt,也就是头文件的格式。
2、客户端
struct.pack(fmt,v1,v2.....)
3、服务器端
(1)struct.calcsize(fmt),可以计算大小,这样就可以在接收端接收指定大小的数据。这个大小对应头
文件数据的大小。
(2)struct.unpack(fmt,v1,v2.....)
第一种方法最终代码:
#服务器端
import socket
import struct
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(("127.0.0.1",3008))
server.listen(3)
while True:
print("start.......")
sock,adddr = server.accept()
d = sock.recv(struct.calcsize("l"))
total_size = struct.unpack("l",d)
num = total_size[0]//1024
data = b''
for i in range(num):
data += sock.recv(1024)
data += sock.recv(total_size[0]%1024)
with open("11.png","wb") as f:
f.write(data)
sock.close()
sock.close()
#客户端
import socket
import struct
import os
import json
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(("127.0.0.1",3008))
print("connect success....")
filepath = "1.png"
size = os.stat(filepath).st_size
f= struct.pack("l",os.stat(filepath).st_size)
client.send(f)
img = open(filepath,"rb")
client.sendall(img.read())
img.close()
client.close()
××××××××××××方法二(推荐):
方法二:
发送端(事先知道接收的缓冲区大小buf)
1、读取要发送的文件,获取总大小
2、每次发送buf大小的数据,是的接收端正好接这么多
3、一直发,直到把文件的数据发送完
接收端
1、一直接收直到数据的不大于0
第二种方法最终代码:
#服务器
import socket
import struct
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(("127.0.0.1",3008))
server.listen(3)
while True:
print("start......")
sock,adddr = server.accept()
total_data = b''
num = 0
data = sock.recv(1024)
total_data += data
num =len(data)
# 如果没有数据了,读出来的data长度为0,len(data)==0
while len(data)>0:
data = sock.recv(1024)
num +=len(data)
total_data += data
with open("11.png","wb") as f:
f.write(total_data)
sock.close()
sock.close()
#客户端
import socket
import struct
import os
import json
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(("127.0.0.1",3008))
print("connect success.....")
filepath = "1.png"
img = open(filepath,"rb")
# print(len(img.read()))
client.sendall(img.read())
img.close()
client.close()
精华推荐