0

asyncioPython 3.5.1の新しいモジュールを試してみたかったのです。ここに私のテストコードがあります:

import asyncio

class EchoClientProtocol:
    def __init__(self, message, loop):
        self.message = message
        self.loop = loop
        self.transport = None

    def connection_made(self, transport):
        self.transport = transport
        print('Send:', self.message)
        self.transport.sendto(self.message.encode())
        self.transport.close()

    def datagram_received(self, data, addr):
        print("Received:", data.decode())

        print("Close the socket")
        #self.transport.close()

    def error_received(self, exc):
        print('Error received:', exc)

    def connection_lost(self, exc):
        print("Socket closed, stop the event loop")
        loop = asyncio.get_event_loop()
        loop.stop()

loop = asyncio.get_event_loop()
message = "Hello World!"
connect = loop.create_datagram_endpoint(
    lambda: EchoClientProtocol(message, loop),
    remote_addr=('127.0.0.1', 9999))
transport, protocol = loop.run_until_complete(connect)
loop.run_forever()
transport.close()
loop.close()

これを実行すると、インタープリターは次のように表示します。

Traceback (most recent call last):
  File "C:\Users\oxygen\Documents\GitProjects\tests\python\udp\client.py", line
35, in <module>
    loop.run_forever()
  File "C:\Python35-32\lib\asyncio\base_events.py", line 295, in run_forever
    self._run_once()
  File "C:\Python35-32\lib\asyncio\base_events.py", line 1218, in _run_once
    event_list = self._selector.select(timeout)
  File "C:\Python35-32\lib\selectors.py", line 314, in select
    r, w, _ = self._select(self._readers, self._writers, [], timeout)
  File "C:\Python35-32\lib\selectors.py", line 305, in _select
    r, w, x = select.select(r, w, w, timeout)
OSError: [WinError 10038] an operation was attempted on something that is not a socket

self.transport.sendto(self.message.encode())これはとのシーケンスが原因だと思いますself.transport.close()。私が正しく理解していれば、sendtoメソッドは非同期であり、メソッドを呼び出してソケットを閉じた後に実際に呼び出されますclose。これを解決する方法はありますか?

4

2 に答える 2

0

DatagramTransport実際には_SelectorDatagramTransport)接続時に2つのアクションをスケジュールします。最初のアクションはconnection_made指定されたプロトコルからのもので、2番目は_read_ready(recvfrom)です-その順序で(https://github.com/python/asyncio/blob/master/asyncio/selector_events.py #L996 )。

でトランスポートを閉じているためconnection_made、次のアクション ( _read_ready) は失敗します。self.transport.close()そこから外します。

asyncio udp examplesが興味深いかもしれません。

于 2016-06-30T00:06:07.307 に答える
0

これは、送信後に on_con_lost の未来を解決します。

import asyncio


class EchoClientProtocol:
    def __init__(self, message, on_con_lost):
        self.message = message
        self.on_con_lost = on_con_lost

    def connection_made(self, transport):
        print("Send:", self.message)
        self.transport = transport
        self.transport.sendto(self.message.encode())
        self.on_con_lost.set_result(True)


async def main() -> None:
    loop = asyncio.get_running_loop()
    transport, protocol = await loop.create_datagram_endpoint(
        lambda: EchoClientProtocol(
            "Hello World!",
            on_con_lost=loop.create_future(),
        ),
        remote_addr=("127.0.0.1", 9999),
    )

    try:
        await asyncio.sleep(0.5)
        await protocol.on_con_lost
    finally:
        transport.close()


if __name__ == "__main__":
    asyncio.run(main())
于 2021-04-06T04:40:44.650 に答える