An asyncio example
Adam Bartoš
drekin at gmail.com
Sat Jul 4 08:20:01 EDT 2015
On Sat, Jul 4, 2015 at 1:07 PM, Adam Bartoš <drekin at gmail.com> wrote:
> 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.
>
>
> There is a bug. See http://bugs.python.org/issue24539 .
>
>
The following code also works.
import asyncio
import socket
async def server(reader, writer):
print("server is starting")
print("server is going to receive a request")
request = (await reader.read()).decode()
print("server received request {!r}".format(request))
response = "RESPONSE"
writer.write(response.encode())
print("server sent response {!r}".format(response))
writer.write_eof()
print("server sent EOF")
print("server is finishing")
async def client(reader, writer):
print("client is starting")
request = "REQUEST"
writer.write(request.encode())
print("client sent request {!r}".format(request))
writer.write_eof()
print("client sent EOF")
print("client is going to receive a response")
response = (await reader.read()).decode()
print("client received response {!r}".format(response))
print("client is finishing")
class FixedStreamReaderProtocol(asyncio.StreamReaderProtocol):
def eof_received(self):
super().eof_received()
return True # keep alive
async def open_connection(*, loop, sock):
reader = asyncio.StreamReader(loop=loop)
protocol = FixedStreamReaderProtocol(reader, loop=loop)
transport, _ = await loop.create_connection(lambda: protocol,
sock=sock)
writer = asyncio.StreamWriter(transport, protocol, reader, loop)
return reader, writer
async def connect(loop):
serversock, clientsock = socket.socketpair()
reader, writer = await open_connection(sock=serversock, loop=loop)
server_coro = server(reader, writer)
reader, writer = await open_connection(sock=clientsock, loop=loop)
client_coro = client(reader, writer)
server_task = loop.create_task(server_coro)
client_task = loop.create_task(client_coro)
return server_task, client_task
loop = asyncio.get_event_loop()
server_task, client_task = loop.run_until_complete(connect(loop))
loop.run_until_complete(server_task)
loop.run_until_complete(client_task)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20150704/2ba8dcbb/attachment.html>
More information about the Python-list
mailing list