2016-10-17 5 views
2

socket(AF_INET, SOCK_DGRAM)で作成したソケットオブジェクトをasyncioループで使用します。しかし、https://docs.python.org/3/library/asyncio-eventloop.html#low-level-socket-operationsにはsendtoの機能が見つかりませんでした。socket.sendtoが非ブロック操作であると想定するのは安全でしょうか?

この関数はasyncioループ内で呼び出すことができるノンブロッキングシステムコールであると見なすことはできますか?または、run_in_executorと別のスレッドで実行するために提出する必要がありますか?

** Documentationは、ループ全体をブロックする可能性があるという懸念があるシステムコールを実行すると述べています。

+0

[2432814](http://stackoverflow.com/questions/2432814/python-blocking-sockets-send-returns-immediately)duplicate? – ldavid

+1

「search Q&A」の投稿を紛失して申し訳ありません。私は「sendto non-blocking」、「asyncioループで使うsendtoは安全です」などのキーワードで検索していました。 – SpringMaple

答えて

3

いいえ、socket.sendtoは非ブロックであるとは限りません。 ADDR(A transport->依存ターゲットアドレス)によって与えられたリモートピアにデータバイトを送信

代わりに、DatagramTransport.sendtoを使用します。 addrがNoneの場合、データはトランスポート作成時に指定されたターゲットアドレスに送信されます。

この方法はブロックされません。は、データをバッファリングし、非同期に送信するように手配します。

データグラムの輸送はloop.create_datagram_endpointコルーチンで返されます。

transport, protocol = await loop.create_datagram_endpoint(factory, sock=sock) 

EDIT - あなたのコメントについて:

は(transport.sendtoに相当socket.sendto()です)?

はありません、それはtransport.sendto操作ノンブロッキングを作るためにloop.add_writerを使用して、ではありません。 implementationを参照してください。

このメソッドは、コールバックスタイルのプロトコルでデータを受け取るように実装されているため、このメソッドを使用したくありません。

低レベルのasyncioはコールバックに基づいており、asyncioはUDPにコルーチンベースのオブジェクトを提供しません。しかし、私はmodule that provides high-level UDP endpoints for asyncioと書いています。

使用法:

async def main(): 
    local = await open_local_endpoint() 
    remote = await open_remote_endpoint(*local.address) 
    remote.write(b'Hey Hey, My My') 
    data, addr = await local.read() 
    message = "Got {data!r} from {addr[0]} port {addr[1]}" 
    print(message.format(data=data.decode(), addr=addr)) 

出力:

Got 'Hey Hey, My My' from 127.0.0.1 port 45551 
+0

socket.sendto()はtransport.sendto()と同じですか?コールバックスタイルで 'protocol'を使ってデータを受け取るようにする実装があるので、私はこのメソッドを使いたくありません。私は[sendto ... recv ... recv ...(ループ)し、次に何かをしたいと思います。私はこれを解決策として受け入れます、ありがとう! – SpringMaple

+0

@SpringMaple問題はありません、私の編集を参照してください。 – Vincent

+0

ありがとう、あなたのモジュールは私を大きく助けました。 – SpringMaple

-1

sendto()はノンブロッキングで、ライターが現在利用できない場合(BlockingIOErrorInterruptedError)を上げるかもしれません。 socket.sendto()transport.sendto()の違いは、最初にsocket.sendto()を呼び出しようとするか、またはソケットがloop.add_writer()で書き込み可能になるのを待ってから、最初に試行しても失敗した場合にはsocket.sendto()に再度呼び出します。

これは、Python 3.5のasyncioモジュールのソースコードから見たものです。2(Windowsの32ビット)

EDIT:Windowsの中

、ソケット操作阻止行動はsocket.settimeoutで指定されたので、その操作はブロックしないように0にタイムアウト値を設定してくださいされています。

関連する問題