Reputation: 6180
Why is my client timing out at code line:
response = yield from asyncio.wait_for(reader.read(), timeout=3.0)
instead of getting a message back?
The server piece only registers it got a message from this client after the client times out and I actually issue a ctrl + d
to kill the Python interpreter
@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()
Upvotes: 3
Views: 1724
Reputation: 94891
The problem is likely that you're calling reader.read()
on the server-side (and also on the client-side), which will block until an EOF
is sent from the server. But presumably you're not doing that - you're just sending some bytes over and keeping the connection open.
Instead, you need either to call readline()
and make sure to append b'\n'
to your mess payloads, call read
with some size to limit the number of bytes you wait for, or call writer.write_eof()
after writing your message payload, assuming you don't plan to use the writer
anymore. Using readline()
or write_eof
are probably your safest options. Here's a complete example demonstrating using readline()
:
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()
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()
And here are the changes to use write_eof()
:
@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()
@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()
Upvotes: 3