遇到的问题
网上找了一些代码,都是只能建立一次socket传输一张图片,然后断开重新连重新传。而建立一次socket代价不小,反复建立会非常消耗系统资源,因此尝试自己通过一次socket连续传输多张图片
代码问题记录(需要代码的可以直接文末)
在做的过程中发现了一些问题:
- socket在传一张图片时是以二进制流的形式传输,图片的二进制流比较大,一般一次传不完,要传很多次。那么接受者是如何知道什么时候才停止接收这张图片呢?那可以让发送者在发图之前先发一个头信息,告诉接收者这个二进制流有多长,然后接收者通过这个来判断是否传完。
- 这个问题是最让我致命的,由于发送者先发了一个头信息,使用socket.send()函数,然后发送图片也是要用socket.send()函数,接收端使用的是socket.recv(1024)函数,1024是缓存大。麻烦来了,由于发送者使用连续的两个send,而socket.recv(1024)是有缓存的,他会把这两个信息缓存到一起去,信息头和图片信息全被缓存了!!!这会直接导致代码接收逻辑错误。我的做法是,不能有两个send同时出现,那么我就在send中间加一个recv函数(阻塞函数),也就是发送者每发一个消息,接收者就立马回复一个消息,这样就保证了不会连续send
代码
由于项目存在两种数据源,一种是可见光,一种是红外,所以我最开始还要制作一个信息头,每次发送的时候要告诉接收者这是什么类型的数据,然后再接收
制作不易,记得给个赞哈!
客户端clien.py
server_address = ('127.0.0.1', 8000)
def send(dir_name, data_format, file_name):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(server_address)
sock.send('{}|{}'.format(data_format, file_name).encode())
reply = sock.recv(1024)
file_list = os.listdir(dir_name)
file_list.sort(key=lambda x: int(x[:-4]))
if 'ok' == reply.decode():
i = 0
print(len(file_list))
for file_name in file_list:
data = file_deal(os.path.join(dir_name, file_name))
sock.send('{}|{}'.format(len(data), file_name).encode())
sock.recv(1024)
go = 0
total = len(data)
while go < total:
data_to_send = data[go:go + total//2]
sock.send(data_to_send)
go += len(data_to_send)
sock.recv(1024).decode()
i += 1
if i < len(file_list):
sock.send(b'continue')
sock.send(b'over')
sock.close()
sys.exit(0)
def file_deal(file_path):
mes = b''
try:
file = open(file_path, 'rb')
mes = file.read()
except:
print('error{}'.format(file_path))
else:
file.close()
return mes
服务端server.py
LOCAL_IP = '127.0.0.1'
PORT = 8000
def server():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((LOCAL_IP, PORT))
sock.listen(3)
while True:
sc, sc_name = sock.accept()
print('收到{}机器请求'.format(sc_name))
info = sc.recv(1024)
print(info)
try:
data_format, directory_name = info.decode().split("|")
sc.send(b'ok')
except:
print('协议头不对,自动断开连接')
sc.close()
continue
if not os.path.exists(directory_name):
os.mkdir(directory_name)
while True:
head_info = sc.recv(1024)
length, file_name = head_info.decode().split('|')
sc.send(b'ok')
if length and file_name:
print(file_name)
newfile = open(os.path.join(directory_name, file_name), 'wb')
file = b''
total = int(length)
get = 0
while get < total:
data = sc.recv(total//2)
file += data
get = get + len(data)
sc.send(b'ok')
print('应该接收{},实际接收{}'.format(length, len(file)))
if file:
print('actually length:{}'.format(len(file)))
newfile.write(file[:])
newfile.close()
reply = sc.recv(1024)
if reply.decode() == "over":
break
server()
参考文章
https://blog.csdn.net/hfutzhouyonghang/article/details/86624684
|