forked from methane/echoserver
-
Notifications
You must be signed in to change notification settings - Fork 0
/
server_tornado.py
executable file
·102 lines (87 loc) · 2.85 KB
/
server_tornado.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#!/usr/bin/env python
import errno
import functools
import socket
from tornado import ioloop, iostream
NONBLOCKING = (errno.EAGAIN, errno.EWOULDBLOCK)
def conn_handler(sock):
buf = [""]
wait_write = [0]
def close():
io_loop.remove_handler(sock.fileno())
sock.close()
def handle(fd, events):
_buf = buf[0]
try:
_buf += sock.recv(1024)
if not _buf:
return close()
except socket.error as e:
if e.args[0] not in NONBLOCKING:
print e
return close()
try:
sent = sock.send(_buf)
buf[0] = _buf = _buf[sent:]
if _buf and not wait_write[0]:
io_loop.modify_handler(fd, io_loop.READ | io_loop.WRITE)
wait_write[0] = 1
elif wait_write[0]:
io_loop.modify_handler(fd, io_loop.READ | io_loop.WRITE)
wait_write[0] = 0
except socket.error as e:
if e.args[0] not in NONBLOCKING:
print e
return _close()
io_loop.add_handler(sock.fileno(), handle, io_loop.READ)
class Connection(object):
__slots__ = ('_conn', '_buf')
def __init__(self, connection):
self._conn = connection
self._buf = ""
io_loop.add_handler(connection.fileno(), self.handle, io_loop.READ)
def handle(self, fd, events):
try:
self._buf += self._conn.recv(1024)
if not self._buf:
return self._close()
except socket.error as e:
if e.args[0] not in NONBLOCKING:
print e
return self._close()
try:
sent = self._conn.send(self._buf)
self._buf = self._buf[sent:]
except socket.error as e:
if e.args[0] not in NONBLOCKING:
print e
return self._close()
def _close(self):
io_loop.remove_handler(self._conn.fileno())
self._conn.close()
self._conn = None
def connection_ready(sock, fd, events):
while True:
try:
connection, address = sock.accept()
except socket.error, e:
if e[0] not in (errno.EWOULDBLOCK, errno.EAGAIN):
raise
return
connection.setblocking(0)
#Connection(connection)
conn_handler(connection)
if __name__ == '__main__':
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setblocking(0)
sock.bind(("", 5000))
sock.listen(1024)
io_loop = ioloop.IOLoop.instance()
callback = functools.partial(connection_ready, sock)
io_loop.add_handler(sock.fileno(), callback, io_loop.READ)
try:
io_loop.start()
except KeyboardInterrupt:
io_loop.stop()
print "exited cleanly"