Python ASYNCOREの問題AF_UNIXソケットを操作します
-
13-11-2019 - |
質問
AF_UNIXソケットを使用したASYNCOREを使用していくつかの問題があります。このコード
import asyncore, socket, os
class testselect(asyncore.dispatcher):
path = '/tmp/mysocket'
def __init__(self):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_UNIX, socket.SOCK_DGRAM)
self.bind(self.path)
self.buffer = 'buffer'
def handle_connect(self):
print 'handle_connect'
pass
def handle_close(self):
print 'handle_close'
if os.path.exists(self.path)
os.remove(self.path)
self.close()
def handle_read(self):
print 'handle_read'
print self.recv(8192)
def writable(self):
print 'writable'
return (len(self.buffer) > 0)
def handle_write(self):
print 'handle_write'
sent = self.send(self.buffer)
self.buffer = self.buffer[sent:]
client = testselect()
asyncore.loop()
.
コードを実行した場合
$ python select_prova.py
writable
handle_connect
handle_write
handle_close
$
.
すぐに終了し、読み書きを待ちません。常にFalse
を返すようにコードを変更するようにコードを変更した場合、入力のために正しく待機して、こののようにSocatと通信できます。
$ socat readline UNIX:/tmp/mysocket
.
読み取り専用の場合(Writable()はFalse
を返すため、論理的には機能しません)。私のコードにエラーがあるか、ASYNCORE / SELECT()でAF_UNIXソケットを管理できませんか?
解決
注他の回答が指しているので、受信側を指定する必要があるデータグラムを送信するとき。それが立っているので、あなたのtestselect
クラスはサーバーよりもクライアントのように見えます。
これらのいくつかを確認します。 asyncore examples
の例は、希望するものに近い - TimeChannel
をsocket.AF_INET
に変更し、バインドアドレスのソケットパスを使用してUNIXドメインソケットを使用します。
通常、UDP INETソケットの作成を示す一般的なsocket.AF_UNIX
を設定します。 UNIXドメインソケットはIPCの形式です。 socket.SOCK_DGRAM
に変更し、socket.SOCK_STREAM
を呼び出して、self.listen([backlog])
などを実装する必要があります。
af_unixでsock_dgramを使用した場合、サーバが終了するのは、handle_accept()
を起動するとwritable
を表示しているため、handle_write
が実行され、'buffer'
をただちに含むパケットを送信します。
返信前にパケットを受信するまでサーバーが待機したい場合は、handle_connect
またはhandle_read
:にバッファを設定してください。
def __init__(self):
...
self.buffer = ''
def handle_connect(self):
self.buffer = 'buffer'
.
サーバーを起動すると、socat
からパケットを受信するまで待機します。
あなたの例を改装するためにあなたの例を書き直しました:
import asyncore, socket, os
class testselect(asyncore.dispatcher):
path = '/tmp/mysocket'
def __init__(self):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_UNIX, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind(self.path)
self.listen(5)
def handle_accept(self):
client = self.accept()
if client is None:
pass
else:
handler = testhandler(*client)
class testhandler(asyncore.dispatcher_with_send):
def __init__(self, sock, addr):
asyncore.dispatcher_with_send.__init__(self, sock)
self.addr = addr
self.buffer = 'greetings'
def handle_read(self):
print self.recv(8192)
def writable(self):
return (len(self.buffer) > 0)
def handle_write(self):
self.send(self.buffer)
self.buffer = ''
def handle_close(self):
self.close()
server = testselect()
try:
asyncore.loop()
finally:
if os.path.exists(testselect.path):
os.unlink(testselect.path)
. 他のヒント
あなたの難易度はSock_Dgramを使っているという事実に煮ることができます。私が知ることができるものから、基本的にasyncore(No recvfrom
またはsendto
)でSOCK_DGRAMソケットを効果的に処理できません。さらに、SocatはSOCK_DGRAM UNIXドメインソケットを操作する方法を持っていないようです。
SOCK_DGRAMソケットには、接続の実際の概念がないため、常に選択通話で書き込み可能に登録します。しかし、実際にwrite
を実行すると、宛先アドレスを指定していないため失敗します。
他の答えは用語が間違っていますが、基本的には正しいです。あなたはここでsock_streamソケットを使う必要があります。