Skip to content

Instantly share code, notes, and snippets.

@limboinf
Created May 31, 2016 10:29
Show Gist options
  • Save limboinf/e99f30555f3abfba37c6f7e0676fb2d5 to your computer and use it in GitHub Desktop.
Save limboinf/e99f30555f3abfba37c6f7e0676fb2d5 to your computer and use it in GitHub Desktop.
Python implements a http server by epoll(version 2.2, epoll, level-triggered, TCP_CORK)
# coding=utf-8
"""
TCP_CORK 参数可以设置缓存消息直到一起被发送
这个选项, 在下例中的45和53行使用
适合给一个实现 http/1.1pipelining 的服务器来使用.
:copyright: (c) 2016 by fangpeng(@beginman.cn).
:license: MIT, see LICENSE for more details.
"""
import socket
import 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)
# 使用 TCP_CORK 参数可以设置缓存消息直到一起被发送
connections[fileno].setsockopt(socket.IPPROTO_TCP, socket.TCP_CORK, 1)
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:
# TCP_CORK 参数可以设置缓存消息直到一起被发送
connections[fileno].setsockopt(socket.IPPROTO_TCP, socket.TCP_CORK, 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()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment