asyncore は非同期ソケット パッケージであり、特にディスパッチャー クラスには非同期呼び出し用のソケット操作メソッドが多数含まれており、Python での asyncore 非同期モジュールの使用法と
基本
を説明しましょう。 このモジュールはソケットの非同期実装です。まず、モジュール内のいくつかのクラスとメソッドについて理解しましょう:
1.asyncore.loop
パス カウントまたは開いたチャネルが閉じるまで、ポーリング ループに入ります。
2.asyncore.dispatcher
ディスパッチャクラスは、基礎となるソケットクラスのラッパーオブジェクトです。より便利にするために、ループ内で非同期に呼び出されるイベント処理メソッドがいくつかあります。それ以外の場合は、標準の非ブロッキング ソケット オブジェクトです。
低レベル イベントは、特定の高レベル イベントが特定のイベントまたは特定の接続状態で発生したことを非同期ループに伝えます。たとえば、別のホストに接続するにはソケットが必要です。
(1) handle_connect() の最初の読み取りまたは書き込みイベント。
(2) handle_close() 読み取りイベントに使用できるデータがありません。
(3) handle_accept 読み取りイベントはソケットをリッスンします。
(4) handle_read
は、チャネルが read() を呼び出していることを非同期ループが検出したときに呼び出されます。
(5) handle_write
は、書き込み可能なソケットに書き込むことができることを非同期ループが検出したときに呼び出されます。多くの場合、このアプローチによりバッファリングのパフォーマンスが実現されます。例:
def handle_write(self): sent = self.send(self.buffer) self.buffer = self.buffer[sent:]
(6) handle_expt
(OOB) データソケット接続がある場合。 OOB はサポートが不十分で、ほとんど使用されないため、このようなことはほとんど起こりません。
(7) handle_connect
ソケットが接続を作成するときに呼び出されます。
(8) handle_close
ソケット接続が閉じられるときに呼び出されます。
(9) handle_error
例外が発生し、他に処理がない場合に呼び出されます。
(10) handle_accept
ローカルリスニングチャネルがリモートエンドとの接続 (パッシブ接続) を確立するときに呼び出されます。
(11) readable
チャネルソケットを読み取りイベントリストに追加するかどうかを決定するために非同期ループ内で毎回呼び出されます。デフォルトは True です。
(12) writable
チャネルソケットを書き込みイベントリストに追加するかどうかを決定するために非同期ループ内で毎回呼び出されます。デフォルトは True です。
(13) create_socket
は標準ソケットを作成する場合と同じです。
(14) connect
は、標準ソケットのポート設定と同じで、最初のパラメータがホストアドレス、2 番目のパラメータがポート番号であるタプルを受け入れます。
(15) send
データをリモートソケットに送信します。
(16)recv
リモートソケットからbuffer_sizeまでのデータを読み込みます。空の文字列は、チャネルがもう一方の端から閉じられていることを意味します。
(17)listen
ソケット接続をリッスンします。
(18)bind
ソケットをアドレスにバインドします。
(19) accept
は接続を受け入れ、ソケットとリスニングアドレスにバインドする必要があります。
(20)close
ソケットを閉じます。
3.asyncore.dispatcher_with_send
ディスパッチャのサブクラスは、単純なクライアント用に単純なバッファ出力機能を追加し、より複雑なクライアントでは asynchat.async_chat を使用します。
4.asyncore.file_dispatcher
file_dispatcher は、survey() 関数またはloop() 関数を使用して、ファイル記述子またはファイルオブジェクトマップとオプションの引数ラッパーを受け取ります。ファイル オブジェクトまたは fileno() メソッドが指定されている場合、そのメソッドが呼び出され、file_wrapper コンストラクターに渡されます。利用可能環境: UNIX。
5.asyncore.file_wrapper
file_wrapper は、整数のファイル記述子を受け取り、os.dup() を呼び出してハンドラーをコピーするため、元のハンドラーは file_wrapper とは独立して閉じることができます。このクラスは、file_dispatcher クラスを使用してソケットをシミュレートするのに十分なメソッドを実装します。利用可能環境: UNIX。
asyncore の例
1. http クライアントの実装。
import socket import asyncore class Client(asyncore.dispatcher): def __init__(self, host, path): asyncore.dispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.connect((host, 80)) self.buffer = 'GET %s HTTP/1.0\r\n\r\n' % path def handle_connect(self): pass def handle_close(self): self.close() def handle_read(self): print self.recv(8192) def writable(self): return (len(self.buffer) > 0) def handle_write(self): sent = self.send(self.buffer) self.buffer = self.buffer[sent:] client = Client('www.python.org', '/') asyncore.loop()
サーバーは接続を受け入れ、タスクを分散します
import socket import asyncore class EchoHandler(asyncore.dispatcher_with_send): def handle_read(self): data = self.recv(8192) if data: self.send(data) class EchoServer(asyncore.dispatcher): def __init__(self, host, port): asyncore.dispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_add() self.bind((host, port)) self.listen(5) def handle_accept(self): pair = self.accept() if pair is not None: sock, addr = pair print 'Incoming connection from %s' % repr(addr) handler = EchoHandler(sock) server = EchoServer('localhost', 8080) asyncore.loop()
2. asyncoreのポートマッピング(ポート転送)を使用します
import socket,asyncore class forwarder(asyncore.dispatcher): def __init__(self, ip, port, remoteip,remoteport,backlog=5): asyncore.dispatcher.__init__(self) self.remoteip=remoteip self.remoteport=remoteport self.create_socket(socket.AF_INET,socket.SOCK_STREAM) self.set_reuse_addr() self.bind((ip,port)) self.listen(backlog) def handle_accept(self): conn, addr = self.accept() # print '--- Connect --- ' sender(receiver(conn),self.remoteip,self.remoteport) class receiver(asyncore.dispatcher): def __init__(self,conn): asyncore.dispatcher.__init__(self,conn) self.from_remote_buffer='' self.to_remote_buffer='' self.sender=None def handle_connect(self): pass def handle_read(self): read = self.recv(4096) # print '%04i -->'%len(read) self.from_remote_buffer += read def writable(self): return (len(self.to_remote_buffer) > 0) def handle_write(self): sent = self.send(self.to_remote_buffer) # print '%04i <--'%sent self.to_remote_buffer = self.to_remote_buffer[sent:] def handle_close(self): self.close() if self.sender: self.sender.close() class sender(asyncore.dispatcher): def __init__(self, receiver, remoteaddr,remoteport): asyncore.dispatcher.__init__(self) self.receiver=receiver receiver.sender=self self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.connect((remoteaddr, remoteport)) def handle_connect(self): pass def handle_read(self): read = self.recv(4096) # print '<-- %04i'%len(read) self.receiver.to_remote_buffer += read def writable(self): return (len(self.receiver.from_remote_buffer) > 0) def handle_write(self): sent = self.send(self.receiver.from_remote_buffer) # print '--> %04i'%sent self.receiver.from_remote_buffer = self.receiver.from_remote_buffer[sent:] def handle_close(self): self.close() self.receiver.close() if __name__=='__main__': import optparse parser = optparse.OptionParser() parser.add_option( '-l','--local-ip', dest='local_ip',default='127.0.0.1', help='Local IP address to bind to') parser.add_option( '-p','--local-port', type='int',dest='local_port',default=80, help='Local port to bind to') parser.add_option( '-r','--remote-ip',dest='remote_ip', help='Local IP address to bind to') parser.add_option( '-P','--remote-port', type='int',dest='remote_port',default=80, help='Remote port to bind to') options, args = parser.parse_args() forwarder(options.local_ip,options.local_port,options.remote_ip,options.remote_port) asyncore.loop()
詳細Pythonコア非同期モジュールのasyn httpclient の使用法と実装に関する記事は、PHP 中国語 Web サイトに注意してください。