#!/usr/bin/python # -*- coding:utf-8 -*- import socket, select EOL1 = b'\n\n' EOL2 = b'\n\r\n' response = b'HTTP/1.0 200 OK\r\nDate: Mon, 1 Jan 1996 01:01:01 GMT\r\n' response += b'Content-Type: text/plain\r\nContent-Length: 13\r\n\r\n' response += b'Hello, world!' serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) serversocket.bind(('0.0.0.0', 8080)) serversocket.listen(1) serversocket.setblocking(0) epoll = select.epoll() epoll.register(serversocket.fileno(), select.EPOLLIN) try: connections = {}; requests = {}; responses = {} while True: events = epoll.poll(1) for fileno, event in events: if fileno == serversocket.fileno(): connection, address = serversocket.accept() connection.setblocking(0) epoll.register(connection.fileno(), select.EPOLLIN) connections[connection.fileno()] = connection requests[connection.fileno()] = b'' responses[connection.fileno()] = response elif event & select.EPOLLIN: requests[fileno] += connections[fileno].recv(1024) if EOL1 in requests[fileno] or EOL2 in requests[fileno]: epoll.modify(fileno, select.EPOLLOUT) print('-'*40 + '\n' + requests[fileno].decode()[:-2]) elif event & select.EPOLLOUT: byteswritten = connections[fileno].send(responses[fileno]) responses[fileno] = responses[fileno][byteswritten:] if len(responses[fileno]) == 0: epoll.modify(fileno, 0) connections[fileno].shutdown(socket.SHUT_RDWR) elif event & select.EPOLLHUP: epoll.unregister(fileno) connections[fileno].close() del connections[fileno] finally: epoll.unregister(serversocket.fileno()) epoll.close() serversocket.close()
轉載自:http://scotdoyle.com/python-epoll-howto.html. python epoll編程基本上都是從這篇文章開始。
epoll流程:
創建socket
-->綁定socket並監聽
-->創建epoll對象
-->註冊socket到epoll對象,使用epoll的註冊函數對socket進行管理
-->服務器進入循環
-->epoll對象輪詢註冊的socket隊列(即:已經就緒的socket隊列)
-->判斷socket是否是新加入的
->新加入socket:創建socket對象,並調用accept(),然後把socket註冊到epoll
->非新socket,且socket狀態爲可讀,調用recv()。如果接收到的消息包含中斷或exit等字符,修改socket狀態
->非新socket,且狀態爲可寫,調用send函數。
->非新socket,且狀態爲HUP,從註冊函數中刪除socket,並調用close()