您的位置:首页 > 运维架构 > Linux

how to use linux epoll with python

2013-04-16 12:03 573 查看
#!/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()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: