On Sat, Jul 4, 2015 at 1:07 PM, Adam Bartoš <dre...@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)
-- https://mail.python.org/mailman/listinfo/python-list