1

免責事項: これはおそらく非常に基本的な質問ですが、概念を理解していないため、目的を達成できません。

asyncio を使用して基本的なエコー クライアント サーバーを実装しようとしています。ドキュメントに含まれているサンプルから始めました。

私が達成したいのは、クライアントが即時接続以外のときにいつでもサーバーにデータを送信してから応答を読み取ることができる永続的な接続です(存在する場合)。接続は、明示的に閉じるまで両端で開いたままにする必要があります。

私はプロトコルのサンプルでこれをやっています。他の質問/ドキュメントを読むと、を使用してこれを実装できるようですがloop.call_later()、これは本当に良い解決策ですか? Queue理想的には、新しいパケットに即座に応答できるようにするためにa を使用したいと思います。

「MyProtocol. 初期化`:

    @asyncio.coroutine
    def writer():
        global out_queue
        while True:
            packt = yield from out_queue.get()
            print("yeahhh packet yummy")
            data = bytes(packt.to_json(), 'ascii')
            self.transport.write(data)

    asyncio.async(writer())

しかし、これは何もしません。メインクライアントコードから新しいアイテムが挿入されると、すぐにメッセージが出力されると思います。何も起こりません...

さらにデバッグすると、キューがいっぱいになっていることが示されますが、out_queue.get() コルーチンは返されません。最初に、out_queue.put はアイテムを最初の .get() 呼び出しのウェイターにほとんど直接入れますが、まるでループが実行されていないかのようです。これは、クライアント接続全体に使用されるのと同じループです (すべてをスレッドに配置したため、新しいループを作成しました)。私が確認したところ、 .put() 呼び出しから行われた適切な呼び出しはすべてこのループ用です。

念のために言っておきますが、私は pip で asyncio install を使って Python 3.3 でこれを実行しています。

更新:これは、アイテムをキューに挿入しようとする方法です:

def send_packet(loop, queue, packet):
    # this runs in main thread, not the loop thread

    def f():
        print("putting packet into queue")
        queue.put_nowait(packet)  # MUST NOT use .put() as it's a coroutine

    loop.call_soon_threadsafe(f)
    # !!! next one doesn't work !!!
    # loop.call_soon_threadsafe(any_normal_function_with_coroutine_calls())

print決して実行されません。

4

1 に答える 1

1

queue.get() が queue.put() の後に起動しない唯一の理由は、暗黙的なループでキューを作成し (そして、このループからの項目を待機する可能性があります)、別のループ インスタンスを使用してデータをプッシュすることです。

于 2014-11-06T11:05:14.000 に答える