Created
May 31, 2016 10:29
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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