【发布时间】:2021-07-13 22:53:20
【问题描述】:
这里是 server.py
import asyncio
import aiofile
async def handler(reader, writer):
data = await reader.read(n=-1)
addr = writer.get_extra_info('peername')
print('Addr', addr)
# photo_120721_215652.jpg
name = data[:23].decode()
async with aiofile.async_open(name, 'wb') as afp:
await afp.write(data[23:])
print("handler end")
async def main():
server = await asyncio.start_server(handler, '0.0.0.0', 8888)
addr = server.sockets[0].getsockname()
print(f'Serving on {addr}')
async with server:
await server.serve_forever()
asyncio.run(main())
这里是client.py
async def send_photos_to_server(filelist):
retry = 0
for file in filelist:
while True:
try:
reader, writer = await asyncio.open_connection('192.168.1.100', 8888)
except OSError:
while retry != 5:
await asyncio.sleep(3)
retry += 1
else:
break # exit the loop
if retry == 5:
print("No connection after {} retries")
break
name = file.split('/')[-1].encode()
writer.write(name)
await writer.drain()
async with aiofile.async_open(file, 'rb') as afp:
afp_reader = await afp.read(length=-1)
writer.write(afp_reader)
await writer.drain()
writer.close()
await writer.wait_closed()
filelist = ['./photos/photo_120721_215652.jpg',
'./photos/photo_120721_215654.jpg',
'./photos/photo_120721_215656.jpg']
asyncio.run(send_photos_to_server(filelist))
所以这段代码是有效的。但我不确定这是否是正确的方法。每次发送一个新文件,我们都会创建一个新的连接。当然,我可以将所有三个文件打包成一个存档,但我不确定它是否方便。此外,将文件名放入发送消息很不方便,因为在服务器端,我必须以某种方式找到它。那么有人可以解释如何修改此代码以获得更好的实践吗?我刚开始学习异步io,并不擅长。
【问题讨论】:
-
你尝试了什么?您是否尝试在
for-loop 之前打开连接,并在for-loop 之后关闭它?但我认为它需要对handler进行重大更改——它只是为了发送一个文件而创建的。它需要一些循环来发送许多文件。其他问题可能是发送名称 - 它可能会将所有名称作为单个字符串获取。在最后一个文件名之后可能还需要它是姓氏的信息。所以它可能更复杂,使用压缩zip可能更简单。 -
您可以将所有名称作为一个带有分隔符的字符串发送,即。
;和处理程序应使用split(';')来获取名称列表。如果它得到一个名字以上的列表,那么它应该使用将所有文件压缩到一个 zip 文件中。或者它应该发送带有一些标头的数据,该标头将包含每个图像的负载信息,并将所有图像作为一个数据发送。所以你必须创建自己的protocol(描述客户端和服务器应该如何通信的规则——比如在协议中HTTP、FTP、SMTP) -
在正常情况下在数据之前发送文件名 - 每个协议在数据之前发送一些额外的信息(标题)。例如HTTP首先发送标题,下一个空行和下一个数据(正文),另一方可以逐字节读取标题,直到它得到空行(两个ENTERS -
'\n\n'),并且其中一个标题有信息有多少字节有正文- 所以它会知道它必须读取多少字节的数据(正文)。 -
"您尝试了什么?您是否尝试在 for-loop 之前打开连接,并在 for-loop 之后关闭它?但我认为它需要对处理程序进行重大更改 - 它只是为了发送而创建的一个文件”-您在谈论服务器,这很好。它旨在在接收到连接后执行
handler功能,然后将其保存到文件中。我的问题更多是关于客户端及其工作方式。我明白了你对文件名的建议。 -
您不能只更改客户端 - 您还必须更改服务器。如果客户端将使用一个连接和 for-loop 来发送许多文件,那么服务器也必须使用
for-loop 来获取所有文件。
标签: python asynchronous server file-transfer