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