这是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,但并不擅长
服务器使用
protocols
——这是一种规则,描述了一方必须发送什么以及如何在另一方上读取例如
HTTP
首先发送头、下一个空行和下一个数据(body)。其中一个标题包含正文的长度信息另一方首先必须读取数据
byte after byte
,直到它找到空行('n\n'
),然后它有头,它可以找到正文的长度,并读取正确的字节数与创建自己的协议的方法相同
我假设您希望在一个连接中发送所有文件
您可以发送文件数+
\n
,然后使用for
-loop发送文件名+\n
,文件大小+\n
,文件数据另一方也应该做类似的事情——首先读取所有到
\n
的数据以获得文件数,然后使用for
-loop再次读取所有到\n
的数据以获得文件名,读取所有到\n
的数据以获得大小,使用size
读取文件数据它表明,使用zip压缩数据并发送数据可能更简单,而另一方将在这个zip文件中包含所有信息——文件名、大小、数据
当然,您可以减少它,并且仍然以单独的连接发送每个文件
示例代码
server.py
client.py
相关问题 更多 >
编程相关推荐