4

asyncio.Protocolクライアントがサーバーを呼び出すことを目的としたサーバーを使用していますが、サーバーが応答してデータが返されるまで待ってから、クライアントループを停止します。

asyncio doc Echo Client and Server に基づく: https://docs.python.org/3/library/asyncio-protocol.html#protocol-example-tcp-echo-server-and-client、transport.write の結果(...) は呼び出されるとすぐに返されます。

経験を通じて、呼び出しloop.run_until_complete(coroutine)は失敗しますRuntimeError: Event loop is running.

サーバーのメソッドで実行asyncio.sleep(n)data_received()ても効果はありません。

yield from asyncio.sleep(n)両方でサーバーyield from asyncio.async(asyncio.sleep(n))data_received()ハングします。

私の質問は、サーバーが応答を書き込むのを待ってから、制御を戻すにはどうすればよいですか?

4

2 に答える 2

3

クライアント コードを変更する必要はありません。

echo-client.py

#!/usr/bin/env python3.4
import asyncio

class EchoClient(asyncio.Protocol):
    message = 'Client Echo'

    def connection_made(self, transport):
        transport.write(self.message.encode())
        print('data sent: {}'.format(self.message))

    def data_received(self, data):
        print('data received: {}'.format(data.decode()))

    def connection_lost(self, exc):
        print('server closed the connection')
        asyncio.get_event_loop().stop()

loop = asyncio.get_event_loop()
coro = loop.create_connection(EchoClient, '127.0.0.1', 8888)
loop.run_until_complete(coro)
loop.run_forever()
loop.close()

秘訣は、コード (self.transport メソッドを含む) をコルーチンに配置し、値を返す必要があるステートメント、または完了するのに時間がかかるステートメントの前にステートメントを置いて、wait_for()メソッドを使用することです。yield from

echo-server.py

#!/usr/bin/env python3.4
import asyncio

class EchoServer(asyncio.Protocol):
    def connection_made(self, transport):
        peername = transport.get_extra_info('peername')
        print('connection from {}'.format(peername))
        self.transport = transport

    def data_received(self, data):
        print('data received: {}'.format(data.decode()))
        fut = asyncio.async(self.sleeper())
        result = asyncio.wait_for(fut, 60)

    @asyncio.coroutine
    def sleeper(self):
        yield from asyncio.sleep(2)
        self.transport.write("Hello World".encode())
        self.transport.close()

loop = asyncio.get_event_loop()
coro = loop.create_server(EchoServer, '127.0.0.1', 8888)
server = loop.run_until_complete(coro)
print('serving on {}'.format(server.sockets[0].getsockname()))

try:
    loop.run_forever()
except KeyboardInterrupt:
    print("exit")
finally:
    server.close()
    loop.close()

を呼び出してから を呼び出すecho-server.pyecho-client.py、クライアントは で決定されるように 2 秒間待機してasyncio.sleepから停止します。

于 2014-09-05T17:27:16.680 に答える