initial commit: echo server
commit
dd14dee99a
|
@ -0,0 +1,3 @@
|
|||
#/bin/sh
|
||||
|
||||
python2 webserver/server.py
|
|
@ -0,0 +1,86 @@
|
|||
import socket, select
|
||||
|
||||
class Server(object):
|
||||
def __init__(self, port=8080):
|
||||
self.port = port
|
||||
self.listening_socket = socket.socket()
|
||||
self.listening_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self.listening_socket.bind(('127.0.0.1', port))
|
||||
self.listening_socket.listen(5)
|
||||
self.listening_socket.setblocking(0)
|
||||
self.handlers = {self.listening_socket: self}
|
||||
self.clients = []
|
||||
def run(self):
|
||||
reads = [self.listening_socket] + [c.sock for c in self.clients]
|
||||
writes = [c.sock for c in self.clients if c.should_write()]
|
||||
others = [c.sock for c in self.clients]
|
||||
[rlist, wlist, xlist] = select.select(reads, writes, others)
|
||||
print(rlist, wlist, xlist)
|
||||
for readable in rlist:
|
||||
self.handlers[readable].do_read()
|
||||
for writable in wlist:
|
||||
self.handlers[writable].do_write()
|
||||
for otherable in xlist:
|
||||
self.handlers[otherable].do_other()
|
||||
def do_read(self):
|
||||
(sock, addrinfo) = self.listening_socket.accept()
|
||||
c = EchoClient(self, sock, addrinfo)
|
||||
self.clients.append(c)
|
||||
self.handlers[sock] = c
|
||||
def client_closed(self, c):
|
||||
self.clients.remove(c)
|
||||
del self.handlers[c.sock]
|
||||
def close(self):
|
||||
self.listening_socket.close()
|
||||
|
||||
class Client(object):
|
||||
"""docstring for Client"""
|
||||
def __init__(self, parent, sock, addrinfo):
|
||||
self.parent = parent
|
||||
self.sock = sock
|
||||
self.sock.setblocking(0)
|
||||
self.addrinfo = addrinfo
|
||||
self.write_buf = ""
|
||||
self.read_buf = ""
|
||||
self.to_close = False
|
||||
#self.write("test")
|
||||
# self.close()
|
||||
def should_write(self):
|
||||
return len(self.write_buf) > 0 or self.to_close
|
||||
def do_read(self):
|
||||
data = self.sock.recv(4096)
|
||||
if not data: return self.close()
|
||||
self.read_buf += data
|
||||
self.on_data()
|
||||
def do_write(self):
|
||||
if self.write_buf:
|
||||
no_written = self.sock.send(self.write_buf)
|
||||
self.write_buf = self.write_buf[no_written:]
|
||||
if len(self.write_buf) == 0 and self.to_close:
|
||||
self.sock.close()
|
||||
self.parent.client_closed(self)
|
||||
def on_data(self): raise NotImplementedError()
|
||||
def do_other(self): pass
|
||||
def write(self, msg):
|
||||
self.write_buf += msg
|
||||
def close(self):
|
||||
self.to_close = True
|
||||
|
||||
class EchoClient(Client):
|
||||
"""docstring for EchoClient"""
|
||||
def __init__(self, parent, sock, addrinfo):
|
||||
super(EchoClient, self).__init__(parent, sock, addrinfo)
|
||||
def on_data(self):
|
||||
self.write(self.read_buf)
|
||||
self.read_buf = ""
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
s = Server()
|
||||
try:
|
||||
while 1:
|
||||
s.run()
|
||||
except:
|
||||
s.close()
|
||||
raise
|
Loading…
Reference in New Issue