pythonネットワークプログラミング学習epoll多重化


ブロック非ブロック、同期非同期概念を撫でる
ブロックと非ブロックは、呼び出し結果(メッセージ、戻り値)を待つプログラムの状態に注目します.
  • ブロック:現在のプロセス呼び出し結果が返されず、プロセスは
  • を待つ.
  • 非ブロック:現在のプロセス呼び出し結果は返されず、プロセスは
  • を待たない.
    同期と非同期はメッセージ通信メカニズムに注目する
  • 非同期:アクティブにデータを要求した後、他のタスクを処理し続けることができ、IO操作完了の通知(一般的に特殊なインタフェースを呼び出す)
  • を待つことができる.
  • 同期:アクティブに要求してIO操作が完了するのを待ち、データが準備できたら読み書きが完了するのを待ってから
  • に戻ることを指す.
    epoll多重化serverを構築するために必要な基本手順
  • まずソケットサーバを構築し、指定されたipポートにバインドします.
  • ソケットを非ブロックモードsetblocking(0)に設定します.
  • 設定TCP_NODELAYオプションは、サーバがバッファなしでデータを直接交換できるようにします.
  • selectを作成します.epoll()インスタンス
  • を監視するために、ソケットのファイル記述子をepollインスタンスに渡す
  • runメソッドはソケットイベント,EPOLLIN(リードイベント),EPOLLOUT(ライトイベント),EPOLLHOP(異常割り込み)
  • をリスニングする.
    ソケットのレスポンスをSERVER_に設定RES
    import socket                                                                                                                                                                      
    import select                                                                       
                                                                                     
    EOL1 = b'

    '                                                                    EOL2 = b'
    \r
    '                                                                  SERVER_RES = b"""HTTP/1.1 200 OK\r
    Date: Mon, 1 Apr 2016 23:00:01                GMT\r
    Content-Type: text/plain\r
    Content-Length: 25\r
    \r
                         Hello from epoll server!"""                                                                                                                                                                                                                           class EpollServer(object):                                                            def __init__(self, host='localhost', port=9999):                                      self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)                     self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)                   self.sock.bind((host, port))                                                      self.sock.listen(1)                                                               self.sock.setblocking(0)                                                          self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)                   print "Started epoll server(%s:%s)..." % (host, port)                             self.epoll = select.epoll()                                                       self.epoll.register(self.sock.fileno(), select.EPOLLIN)                                                                                                         def run(self):                                                                        try:                                                                                  connections = {}                                                                  requests = {}                                                                     responses = {}                                                                    while True:                                                                           events = self.epoll.poll(1)                                                       for fileno, event in events:                                                          print fileno, event, "......"                                                     if fileno == self.sock.fileno():                                                      connection, address = self.sock.accept()                                          connection.setblocking(0)                                                         self.epoll.register(connection.fileno(), select.EPOLLIN)                         connections[connection.fileno()] = connection                                     requests[connection.fileno()] = b''                                               responses[connection.fileno()] = SERVER_RES                                   elif event & select.EPOLLIN:                                                          requests[fileno] += connections[fileno].recv(1024)                                if EOL1 in requests[fileno] or EOL2 in requests[fileno]:                             self.epoll.modify(fileno, select.EPOLLOUT)                                        print "'-'*40 + '
    ' + requests[fileno].decode()[:-2]"                     elif event & select.EPOLLOUT:                                                         byteswritten = connections[fileno].send(responses[fileno])                         responses[fileno] = responses[fileno][byteswritten:]                              if len(responses[fileno]) == 0:                                                       self.epoll.modify(fileno, 0)                                                      connections[fileno].shutdown(socket.SHUT_RDWR)                            elif event & select.EPOLLHUP:                                                         self.epoll.unregister(fileno)                                                     connections[fileno].close()                         del connections[fileno]                                           finally:                                                                              self.epoll.unregister(self.sock.fileno())                                         self.epoll.close()                                                                self.sock.close()                                                                                                                                                                                                                         if __name__ == '__main__':                                                            server = EpollServer('192.168.199.110', 6789)                                     server.run()

    ブラウザでこのwebサービスにアクセスすると、正常にサービス側に戻って送信されます.
    Hello from epoll server!