An asyncio example

Ian Kelly ian.g.kelly at gmail.com
Sat Jul 4 07:58:45 CEST 2015


On Fri, Jul 3, 2015 at 9:14 AM, Marko Rauhamaa <marko at pacujo.net> wrote:
>
>>> 1) is there a way to close just one direction of the connection?
>>
>> No. SOCK_STREAM sockets are always bidirectional.
>
> socket.shutdown(socket.SHUT_WR) does the trick.
>
> I think the asyncio.StreamWriter.write_eof() is the high-level
> equivalent.

I stand corrected. And you're also correct about write_eof: it causes
shutdown(SHUT_WR) to be called on the underlying socket once the
buffer has been written.

https://hg.python.org/cpython/file/34460219c0e0/Lib/asyncio/selector_events.py#l737

That said, just replacing the writer.close() with writer.write_eof()
in the OP's code doesn't seem to work; the server response comes back
empty.

This works:

>>> sock1, sock2 = socket.socketpair()
>>> sock1.send(b'REQUEST')
7
>>> sock1.shutdown(socket.SHUT_WR)
>>> sock2.recv(100)
b'REQUEST'
>>> sock2.send(b'RESPONSE')
8
>>> sock1.recv(100)
b'RESPONSE'

And this works:

import asyncio
import socket

def server(sock):
    request = yield from asyncio.get_event_loop().sock_recv(sock, 100)
    print("got request {!r}".format(request))
    yield from asyncio.get_event_loop().sock_sendall(sock, b'RESPONSE')

def client(sock):
    yield from asyncio.get_event_loop().sock_sendall(sock, b'REQUEST')
    sock.shutdown(socket.SHUT_WR)
    response = yield from asyncio.get_event_loop().sock_recv(sock, 100)
    print("got response {!r}".format(response))
    asyncio.get_event_loop().stop()

def connect():
    clientsock, serversock = socket.socketpair()
    clientsock.setblocking(False)
    serversock.setblocking(False)
    asyncio.async(client(clientsock))
    asyncio.async(server(serversock))

connect()
asyncio.get_event_loop().run_forever()

I'm wondering whether there might be a bug in the higher-level
transport code that interferes with reading after calling write_eof.


More information about the Python-list mailing list