为什么这个 Python 3 asyncio 客户端仅在 Python 进程中断后才发送字节?
Why is this Python 3 asyncio client sending the bytes only after the Python process is interrupted?
为什么我的客户端在代码行处超时:
response = yield from asyncio.wait_for(reader.read(), timeout=3.0)
而不是收到消息?
服务器部分仅在客户端超时后注册它从该客户端收到消息,我实际上发出 ctrl + d
以终止 Python 解释器
client.py
@asyncio.coroutine
def test_connection(host, port):
# Get the streams for the socket
print('Starting client connection')
reader, writer = yield from asyncio.open_connection(host, port)
message = 'Test Message'.encode('ascii')
# Start communication
print('Sending message to {}:{} - {}'.format(host, port, message))
writer.write(message)
print('Waiting 3 sec for response...')
response = yield from asyncio.wait_for(reader.read(), timeout=3.0)
print('Got response: {}'.format(response.decode('ascii')))
writer.close()
def run():
loop = asyncio.get_event_loop()
task = asyncio.async(test_connection())
loop.run_until_complete(task)
loop.close()
问题很可能是您在服务器端(以及客户端)调用 reader.read()
,这将阻塞直到从服务器发送 EOF
。但大概你并没有这样做 - 你只是发送了一些字节并保持连接打开。
相反,您需要调用 readline()
并确保将 b'\n'
附加到您的混乱负载中,调用 read
一些大小来限制您等待的字节数,或者在编写消息负载后调用 writer.write_eof()
,假设您不打算再使用 writer
。使用 readline()
或 write_eof
可能是最安全的选择。这是一个完整的示例,演示了如何使用 readline()
:
client.py
import asyncio
@asyncio.coroutine
def test_connection(host, port):
# Get the streams for the socket
print('Starting client connection')
reader, writer = yield from asyncio.open_connection(host, port)
message = 'Test Message\n'.encode('ascii')
# Start communication
print('Sending message to {}:{} - {}'.format(host, port, message))
writer.write(message)
print('Waiting 3 sec for response...')
response = yield from asyncio.wait_for(reader.readline(), timeout=5.0)
print('Got response: {}'.format(response.decode('ascii')))
writer.close()
def run():
loop = asyncio.get_event_loop()
task = asyncio.async(test_connection('localhost', 5000))
loop.run_until_complete(task)
loop.close()
run()
server.py
import asyncio
@asyncio.coroutine
def got_connection(reader, writer):
msg = yield from reader.readline()
message = 'another Test Message\n'.encode('ascii')
print('Sending message to {}:{} - {}'.format('localhost', 5000, message))
writer.write(message)
def run():
loop = asyncio.get_event_loop()
server = loop.run_until_complete(asyncio.start_server(
got_connection, 'localhost', 5000))
loop.run_until_complete(server.wait_closed())
loop.close()
run()
下面是使用 write_eof()
的更改:
client.py
@asyncio.coroutine
def test_connection(host, port):
# Get the streams for the socket
print('Starting client connection')
reader, writer = yield from asyncio.open_connection(host, port)
message = 'Test Message'.encode('ascii')
# Start communication
print('Sending message to {}:{} - {}'.format(host, port, message))
writer.write(message)
writer.write_eof()
print('Waiting 3 sec for response...')
response = yield from asyncio.wait_for(reader.read(), timeout=5.0)
print('Got response: {}'.format(response.decode('ascii')))
writer.close()
server.py
@asyncio.coroutine
def got_connection(reader, writer):
msg = yield from reader.read()
message = 'another Test Message'.encode('ascii')
print('Sending message to {}:{} - {}'.format('localhost', 5000, message))
writer.write(message)
writer.write_eof()
为什么我的客户端在代码行处超时:
response = yield from asyncio.wait_for(reader.read(), timeout=3.0)
而不是收到消息?
服务器部分仅在客户端超时后注册它从该客户端收到消息,我实际上发出 ctrl + d
以终止 Python 解释器
client.py
@asyncio.coroutine
def test_connection(host, port):
# Get the streams for the socket
print('Starting client connection')
reader, writer = yield from asyncio.open_connection(host, port)
message = 'Test Message'.encode('ascii')
# Start communication
print('Sending message to {}:{} - {}'.format(host, port, message))
writer.write(message)
print('Waiting 3 sec for response...')
response = yield from asyncio.wait_for(reader.read(), timeout=3.0)
print('Got response: {}'.format(response.decode('ascii')))
writer.close()
def run():
loop = asyncio.get_event_loop()
task = asyncio.async(test_connection())
loop.run_until_complete(task)
loop.close()
问题很可能是您在服务器端(以及客户端)调用 reader.read()
,这将阻塞直到从服务器发送 EOF
。但大概你并没有这样做 - 你只是发送了一些字节并保持连接打开。
相反,您需要调用 readline()
并确保将 b'\n'
附加到您的混乱负载中,调用 read
一些大小来限制您等待的字节数,或者在编写消息负载后调用 writer.write_eof()
,假设您不打算再使用 writer
。使用 readline()
或 write_eof
可能是最安全的选择。这是一个完整的示例,演示了如何使用 readline()
:
client.py
import asyncio
@asyncio.coroutine
def test_connection(host, port):
# Get the streams for the socket
print('Starting client connection')
reader, writer = yield from asyncio.open_connection(host, port)
message = 'Test Message\n'.encode('ascii')
# Start communication
print('Sending message to {}:{} - {}'.format(host, port, message))
writer.write(message)
print('Waiting 3 sec for response...')
response = yield from asyncio.wait_for(reader.readline(), timeout=5.0)
print('Got response: {}'.format(response.decode('ascii')))
writer.close()
def run():
loop = asyncio.get_event_loop()
task = asyncio.async(test_connection('localhost', 5000))
loop.run_until_complete(task)
loop.close()
run()
server.py
import asyncio
@asyncio.coroutine
def got_connection(reader, writer):
msg = yield from reader.readline()
message = 'another Test Message\n'.encode('ascii')
print('Sending message to {}:{} - {}'.format('localhost', 5000, message))
writer.write(message)
def run():
loop = asyncio.get_event_loop()
server = loop.run_until_complete(asyncio.start_server(
got_connection, 'localhost', 5000))
loop.run_until_complete(server.wait_closed())
loop.close()
run()
下面是使用 write_eof()
的更改:
client.py
@asyncio.coroutine
def test_connection(host, port):
# Get the streams for the socket
print('Starting client connection')
reader, writer = yield from asyncio.open_connection(host, port)
message = 'Test Message'.encode('ascii')
# Start communication
print('Sending message to {}:{} - {}'.format(host, port, message))
writer.write(message)
writer.write_eof()
print('Waiting 3 sec for response...')
response = yield from asyncio.wait_for(reader.read(), timeout=5.0)
print('Got response: {}'.format(response.decode('ascii')))
writer.close()
server.py
@asyncio.coroutine
def got_connection(reader, writer):
msg = yield from reader.read()
message = 'another Test Message'.encode('ascii')
print('Sending message to {}:{} - {}'.format('localhost', 5000, message))
writer.write(message)
writer.write_eof()