1 #!/usr/bin/env python
2 #-*- coding:utf-8 -*-
3
4 import socket
5 import select
6 import argparse
7
8 SERVER_HOST = 'localhost'
9
10 EOL1 = b'\n\n'
11 EOL2 = b'\n\r\n'
12 SERVER_RESPOnSE= b'''HTTP/1.1 200 OK\r\nDate: Mon, 1 Apr 2013 01:01:01 GMT\r\nContent-Type: text/plain\r\nContent-Length: 25\r\n\r\nHello from Epoll Server!'''
13
14 class EpollServer:
15 ''' 使用Epoll的Socket服务器 '''
16 def __init__(self, host=SERVER_HOST, port=0):
17 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
18 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
19 self.sock.bind((host, port))
20 self.sock.listen(1)
21 self.sock.setblocking(0)
22 self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
23 print('Epoll Server Started')
24 self.epoll = select.epoll()
25 self.epoll.register(self.sock.fileno(), select.EPOLLIN)
26
27 def run(self):
28 ''' 执行Epoll服务器操作 '''
29 try:
30 cOnnections= {}
31 requests = {}
32 respOnses= {}
33 while True:
34 events = self.epoll.poll(1)
35 for fileno, event in events:
36 if fileno == self.sock.fileno():
37 connection, address = self.sock.accept()
38 connection.setblocking(0)
39 self.epoll.register(connection.fileno(), select.EPOLLIN)
40 connections[connection.fileno()] = connection
41 requests[connection.fileno()] = b''
42 responses[connection.fileno()] = SERVER_RESPONSE
43 elif event & select.EPOLLIN:
44 requests[fileno] += connections[fileno].recv(1024)
45 if EOL1 in requests[fileno] or EOL2 in requests[fileno]:
46 self.epoll.modify(fileno, select.EPOLLOUT)
47 print('-'*40 + '\n' + requests[fileno].decode()[:-2])
48 elif event & select.EPOLLOUT:
49 byteswritten = connections[fileno].send(responses[fileno])
50 responses[fileno] = responses[fileno][byteswritten:]
51 if len(responses[fileno]) == 0:
52 self.epoll.modify(fileno, 0)
53 connections[fileno].shutdown(socket.SHUT_RDWR)
54 elif event & select.EPOLLHUP:
55 self.epoll.unregister(fileno)
56 connections[fileno].close()
57 del connections[fileno]
58 finally:
59 self.epoll.unregister(self.sock.fileno())
60 self.epoll.close()
61 self.sock.close()
62
63 if __name__ == '__main__':
64 parser = argparse.ArgumentParser(description='Socket Server Example with Epoll')
65 parser.add_argument('--port', action='store', dest='port', type=int, required=True)
66 given_args = parser.parse_args()
67 port = given_args.port
68 server = EpollServer(host=SERVER_HOST, port=port)
69 server.run()