<code
class
=
"python"
>import os
import select
import socket
import logging
import time
eventmasks = {
"EPOLLERR"
: 8,
"EPOLLET"
: 2147483648,
"EPOLLHUP"
: 16,
"EPOLLIN"
: 1,
"EPOLLMSG"
: 1024,
"EPOLLONESHOT"
: 1073741824,
"EPOLLOUT"
: 4,
"EPOLLPRI"
: 2,
"EPOLLRDBAND"
: 128,
"EPOLLRDNORM"
: 64,
"EPOLLWRBAND"
: 512,
"EPOLLWRNORM"
: 256,
}
eventmask_ids = {
1:
"EPOLLIN"
,
2:
"EPOLLPRI"
,
4:
"EPOLLOUT"
,
8:
"EPOLLERR"
,
16:
"EPOLLHUP"
,
64:
"EPOLLRDNORM"
,
128:
"EPOLLRDBAND"
,
256:
"EPOLLWRNORM"
,
512:
"EPOLLWRBAND"
,
1024:
"EPOLLMSG"
,
1073741824:
"EPOLLONESHOT"
,
2147483648:
"EPOLLET"
}
formatter =
"[%(asctime)-15s] [%(levelname)s] %(message)s"
logging.basicConfig(level=logging.DEBUG, format=formatter)
EOL1 = b
'\n\n'
EOL2 = b
'\n\r\n'
response = b
'HTTP/1.0 200 OK\r\nDate: %s\r\n'
response += b
'Content-Type: text/plain\r\nContent-Length: %s\r\n\r\n%s'
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((
"0.0.0.0"
, 9999))
s.listen(1024)
s.setblocking(0)
epoll = select.epoll()
s_fileno = s.fileno()
epoll.register(s, select.EPOLLIN)
try
:
connections = {}
request_data = {}
response_data = {}
actions = {}
while
True:
events = epoll.poll(24)
for
fileno, event in events:
logging.debug(
">>>>>"
* 12)
logging.debug(
"Event file number is %s and event mask is %s(%s)"
, fileno, bin(event), eventmask_ids.get(event, 0))
if
fileno == s_fileno:
# create
new
socket connection from client
conn, address = s.accept()
conn.setblocking(0)
c_fileno = conn.fileno()
logging.debug(
"Connection from client%s file number is %s"
, address, c_fileno)
epoll.register(c_fileno, select.EPOLLIN)
connections[c_fileno] = conn
request_data[c_fileno] = b
""
response_data[c_fileno] = b
""
actions[c_fileno] = []
elif event & select.EPOLLIN:
logging.info(
"Recive data epoll socket file number is %s, actions are: %s"
, fileno, actions[fileno])
actions[fileno].append(
"recv"
)
# data come in
data_piece = connections[fileno].recv(1024)
# logging.debug(
"Recive client data piece is:\n%s"
, data_piece)
request_data[fileno] += data_piece
if
EOL1 in request_data[fileno]
or
EOL2 in request_data[fileno]:
resp = str(os.environ)
response_data[fileno] = response % (time.
strftime
(
"%a, %d %b %Y %H:%M:%S GMT"
, time.gmtime()), len(resp), resp)
epoll.modify(fileno, select.EPOLLOUT)
# logging.debug(
"Data from client is: \n%s"
, request_data[fileno])
if
request_data[fileno] == b
""
:
logging.error(
"Recive empty data"
)
epoll.unregister(fileno)
connections[fileno].close()
elif event & select.EPOLLOUT:
actions[fileno].append(
"send"
)
# send data to client
# logging.warn(
"Full connections are %s"
, connections)
logging.info(
"Send data epoll socket file number is %s"
, fileno)
send_bytes = connections[fileno].send(response_data[fileno])
response_data[fileno] = response_data[fileno][send_bytes:]
if
len(response_data[fileno]) == 0:
actions[fileno].append(
"shutdown"
)
epoll.modify(fileno, 0)
logging.info(
"I will shutdown socket(%s), actions are: %s"
, connections[fileno], actions[fileno])
connections[fileno].shutdown(socket.SHUT_RDWR)
del response_data[fileno]
elif event & select.EPOLLHUP:
actions[fileno].append(
"close"
)
logging.info(
"Close data epoll scoket file number is %s, actions are: %s"
, fileno, actions[fileno])
# connection close by client
epoll.unregister(fileno)
connections[fileno].close()
del connections[fileno]
del actions[fileno]
logging.debug(
"<<<<<"
* 12)
finally:
logging.error(
"Exception happend, closing server..."
)
epoll.unregister(s_fileno)
epoll.close()
s.close()</code>