質問: 上記のサイトにsocket.setblocking(0)は使うべきではないと表記してありますが,単一のクライアントとのみ通信したい場合も使うべきではないのでしょうか? 別のサイトでこのようなビジーループはCPUのメモリを多く使ってしまうという記述を見かけましたが,setblocking(0)を実際にサーバで ``` soc=socket.socket(socket.AF_INET, socket.SOCK_STREAM) soc.bind(('127.0.0.1',65535)) soc.listen(5) soc.setblocking(0) ``` のようにして単一のクライアントと通信するために使ってみたのですが,CPU使用率は1%にも満たず,動作も問題ありませんでした. このような場合はsetblocking(0)を使ってもよいのでしょうか?
回答: socket.setblocking(0)にして、send, recv, connect, acceptで処理をすることを、では、「愚かな解法」と書かれています。ノンブロッキングソケットをsoc.recv()等を使って、効率的な処理をできるようなプログラムを自分で書くのは相当な手間だと思います。単一のクライアントとのみ通信すると限定してしまえば、プログラムを書くのは簡単になりますが、ノンブロッキングソケットを使うメッリトはないと思います。それであれば、ブロッキングソケットで十分だと思います。 ネットワークでのやり取りが増加している現在では、node.jsだと最初から非同期プログラミングが前提となっているように、効率的に処理をするためにノンブロッキングソケットを使うことは多くなってきています。Pythonでは以前からselectを使えたし、最近では`asyncio`モジュールがPython3.4で追加され、その後改善されてきています。もし、必要であればそれらを使えば問題はありません。 以下が公式ドキュメントの「19.5. asyncio — Asynchronous I/O, event loop, coroutines and tasks」にあるTCP echo サーバーの例です。随分楽に書けるようになっています。 ``` import asyncio async def handle_echo(reader, writer): data = await reader.read(100) message = data.decode() addr = writer.get_extra_info('peername') print("Received %r from %r" % (message, addr)) print("Send: %r" % message) writer.write(data) await writer.drain() print("Close the client socket") writer.close() loop = asyncio.get_event_loop() coro = asyncio.start_server(handle_echo, '127.0.0.1', 8888, loop=loop) server = loop.run_until_complete(coro) # Serve requests until Ctrl+C is pressed print('Serving on {}'.format(server.sockets[0].getsockname())) try: loop.run_forever() except KeyboardInterrupt: pass # Close the server server.close() loop.run_until_complete(server.wait_closed()) loop.close() ```