简单 python asyncio 服务器不读取数据
simple python asyncio server does not read data
我正在使用 python3.6 和 windows10 上的 asyncio 来制作一个简单的服务器。我在让服务器按我想要的方式工作时遇到问题。
但是使用套接字接口实现的同一个服务器可以按预期工作。
这是工作服务器
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(('', 3201))
s.listen(1)
conn, addr = s.accept()
with conn:
print('Client connection: {}:{}'.format(*addr))
while True:
data = conn.recv(1024)
if data:
print('recv {} bytes'.format(len(data)))
else:
print('no data')
break
print('connection closed')
我用nc命令测试了一下。例如
nc 10.68.100.32 3201
abc
ab
a
^C
服务器打印:
Client connection: 10.68.101.87:55243
recv 4 bytes
recv 3 bytes
recv 2 bytes
no data
connection closed
但我不能用 asyncio 做同样的服务器。
这是一个协议版本:
import asyncio
class ListenServer(asyncio.Protocol):
def connection_made(self, transport):
address = transport.get_extra_info('peername')
print('connection made by client:{}:{}'.format(*address))
def data_deceived(self, data):
print('received {}'.format(len(data)), flush=True)
def eof_received(self):
print('print received EOF')
def connection_lost(self, error):
if error:
print('ERROR: {}'.format(error))
else:
print('connection closed')
event_loop = asyncio.get_event_loop()
factory = event_loop.create_server(ListenServer, '', 3201)
server = event_loop.run_until_complete(factory)
event_loop.run_forever()
print('closing server')
server.close()
对于与上述服务器相同的 nc 测试序列,服务器写入:
connection made by client:10.68.101.87:55247
print received EOF
connection closed
我也失败了服务器的 asyncio 协程 API 版本:
import asyncio
async def just_read(reader, writer):
cli_host, cli_port = writer.get_extra_info('peername')
print('Client connected {}:{}'.format(cli_host, cli_port))
while True:
data = await reader.read()
if data:
print('received {} bytes'.format(len(data)), flush=True)
else:
print('closing')
writer.close()
return
event_loop = asyncio.get_event_loop()
coro = asyncio.start_server(just_read, '', 3201, loop=event_loop)
server = event_loop.run_until_complete(coro)
event_loop.run_forever()
server.close()
print('Connection closed')
这种情况下的输出有点不同:
Client connected 10.68.101.87:55253
received 9 bytes
closing
在这种情况下,当我用 ^C 关闭 nc 时,我得到了所有数据,
服务器继续运行,因此我可以再次连接。
我想让服务器读取并打印出客户端写入的内容,
只要客户端连接,它就应该连接一次并保持连接。
我怎样才能用 asyncio 实现这个,我应该使用协议还是协程版本,这有关系吗?
这只是我希望服务器执行的几项任务中的第一项,可能也是最简单的一项。
此处未显示的其他任务是开始定期发送虚拟消息
并发送对不同消息的响应。
协议代码包含拼写错误,它将方法命名为 data_deceived
而不是 data_received
。更正方法名称后,输出将与阻塞示例中的输出相同。
在协程版本中,问题是reader.read()
指示asyncio收集数据直到end-of-file,并在准备好时提供。将其更改为 reader.read(1024)
,类似于阻塞版本中的 sock.recv(1024)
,修复了代码。
我正在使用 python3.6 和 windows10 上的 asyncio 来制作一个简单的服务器。我在让服务器按我想要的方式工作时遇到问题。 但是使用套接字接口实现的同一个服务器可以按预期工作。 这是工作服务器
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(('', 3201))
s.listen(1)
conn, addr = s.accept()
with conn:
print('Client connection: {}:{}'.format(*addr))
while True:
data = conn.recv(1024)
if data:
print('recv {} bytes'.format(len(data)))
else:
print('no data')
break
print('connection closed')
我用nc命令测试了一下。例如
nc 10.68.100.32 3201
abc
ab
a
^C
服务器打印:
Client connection: 10.68.101.87:55243
recv 4 bytes
recv 3 bytes
recv 2 bytes
no data
connection closed
但我不能用 asyncio 做同样的服务器。 这是一个协议版本:
import asyncio
class ListenServer(asyncio.Protocol):
def connection_made(self, transport):
address = transport.get_extra_info('peername')
print('connection made by client:{}:{}'.format(*address))
def data_deceived(self, data):
print('received {}'.format(len(data)), flush=True)
def eof_received(self):
print('print received EOF')
def connection_lost(self, error):
if error:
print('ERROR: {}'.format(error))
else:
print('connection closed')
event_loop = asyncio.get_event_loop()
factory = event_loop.create_server(ListenServer, '', 3201)
server = event_loop.run_until_complete(factory)
event_loop.run_forever()
print('closing server')
server.close()
对于与上述服务器相同的 nc 测试序列,服务器写入:
connection made by client:10.68.101.87:55247
print received EOF
connection closed
我也失败了服务器的 asyncio 协程 API 版本:
import asyncio
async def just_read(reader, writer):
cli_host, cli_port = writer.get_extra_info('peername')
print('Client connected {}:{}'.format(cli_host, cli_port))
while True:
data = await reader.read()
if data:
print('received {} bytes'.format(len(data)), flush=True)
else:
print('closing')
writer.close()
return
event_loop = asyncio.get_event_loop()
coro = asyncio.start_server(just_read, '', 3201, loop=event_loop)
server = event_loop.run_until_complete(coro)
event_loop.run_forever()
server.close()
print('Connection closed')
这种情况下的输出有点不同:
Client connected 10.68.101.87:55253
received 9 bytes
closing
在这种情况下,当我用 ^C 关闭 nc 时,我得到了所有数据, 服务器继续运行,因此我可以再次连接。
我想让服务器读取并打印出客户端写入的内容, 只要客户端连接,它就应该连接一次并保持连接。 我怎样才能用 asyncio 实现这个,我应该使用协议还是协程版本,这有关系吗?
这只是我希望服务器执行的几项任务中的第一项,可能也是最简单的一项。 此处未显示的其他任务是开始定期发送虚拟消息 并发送对不同消息的响应。
协议代码包含拼写错误,它将方法命名为 data_deceived
而不是 data_received
。更正方法名称后,输出将与阻塞示例中的输出相同。
在协程版本中,问题是reader.read()
指示asyncio收集数据直到end-of-file,并在准备好时提供。将其更改为 reader.read(1024)
,类似于阻塞版本中的 sock.recv(1024)
,修复了代码。