Search code examples
python-asynciostreamreaderstreamwriter

Why StreamReader can't recv in this code?


I have a question about StreamReader/StreamWriter.

To simplify my actual code, just like the following code(they can run). After running the server, run the client to request it. The server will not read any data

Server Code:

import asyncio

loop = asyncio.get_event_loop()


async def log(reader: asyncio.StreamReader, writer: asyncio.StreamWriter):
    print("Wait read")
    data = await reader.read(-1)
    print("<:", data)
    writer.write(data)
    await writer.drain()
    print(">:", data)


async def link(reader: asyncio.StreamReader, writer: asyncio.StreamWriter):
    asyncio.run_coroutine_threadsafe(log(reader, writer), loop)
    print("Connect.")
    await asyncio.sleep(1)


loop.run_until_complete(
    asyncio.start_server(
        link, "0.0.0.0", 1080, loop=loop
    )
)
loop.run_forever()

Client Code:

import socket
import traceback

try:
    sock = socket.create_connection(("127.0.0.1", 1080))
    sock.sendall(b"Hello")
    print(sock.recv(1024))
    sock.close()
except socket.error:
    traceback.print_exc()

I know how to solve this problem, but I want to know why this problem arises.


Solution

  • Accordingly to documentation :

    StreamReader.coroutine read(n=-1)

    Read up to n bytes. If n is not provided, or set to -1, read until EOF and return all read bytes.

    If EOF was received and the internal buffer is empty, return an empty bytes object.

    Your program is waiting on the call data = await reader.read(-1). The reader.read(-1) return only when it receives EOF (End of File). In other words it means it will return when the other side (client) close the socket.

    You can try to experiment and comment out this line print(sock.recv(1024)) in the client code and you will see that data = await reader.read(-1) returns.