Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import select
- from multiprocessing import Process, Array, Value
- import sys
- import time
- def thread(request, response, status, type):
- def thread_return(_message, _status=200, _type=b"text/html"):
- response.value = _message
- type.value = _type
- status.value = _status
- thread_return(b"Hello world")
- return sys.exit(0)
- class Server():
- server = None
- readable = [] # request reading
- writeable = [] # response writeing
- clients = {} # in process
- def __init__(self, host, port):
- import socket
- print("Create HTTP server " + host + ":" + str(port))
- self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self.server.bind((host, port))
- self.server.listen(10)
- self.server.setblocking(0)
- #self.server.settimeout(0)
- def add(self, sock, addr):
- self.readable.append(sock)
- data = {
- "sock": sock,
- "addr": addr,
- "raw_input": b"",
- "data": b"",
- "response": Array("c", 1024*10 * 10),
- "status": Value("d", -1),
- "type": Array("c", 512),
- "timeout": time.time() + 3
- }
- data["type"].value = b"text/html"
- self.clients[sock] = data
- def remove(self, sock):
- addr = self.get(sock)["addr"]
- if sock in self.readable:
- self.readable.remove(sock)
- if sock in self.writeable:
- self.writeable.remove(sock)
- if sock in self.clients:
- del self.clients[sock]
- print(addr + " del")
- sock.close()
- print("Clients after remove: %d, r/w: %d %d" % (len(self.clients), len(self.readable), len(self.writeable)))
- def parseHeaders(self, cli, data):
- print("Start parse headers: " + data)
- data = data.splitlines()
- firstline, headers = data[0], data[1:]
- headers = dict([i.split(": ") for i in headers[1:]])
- if "Content-Length" in headers:
- headers["Content-Length"] = int(headers["Content-Length"])
- firstline = firstline.split(" ")
- method, address, version = firstline[0], firstline[1], firstline[2]
- query = ""
- dquery = {}
- qindex = address.find("?")
- if qindex > 0:
- address, query = address[:qindex], address[qindex+1:]
- for qc in query.split("&"):
- ql = qc.split("=")
- dquery[ql[0]] = (len(ql) == 2) and ql[1] or True
- request = {}
- request["headers"] = headers
- request["query"], request["dquery"] = query, dquery
- request["method"], request["address"], request["proto"] = method, address, version
- print("Finish parse headers " + str(request))
- return request
- def sendResponse(self, cli):
- message = cli["response"].value
- status = cli["status"].value
- type = cli["type"].value
- print("Send response: " + str(len(message)) + " " + str(message)[:50])
- response = b"HTTP/1.0 %d\r\nContent-Type:%s\r\nContent-Length:%d\r\n\r\n%s" % (status, type, len(message), message)
- cli["sock"].send(response)
- cli["sock"].shutdown(1)
- def get(self, sock):
- return self.clients[sock]
- def append(self, cli, data):
- cli["timeout"] = time.time() + 60
- print("Append " + cli["addr"] + " " + str(cli["raw_input"]) + "\n" + str(data) + "\n\n")
- cli["raw_input"] += data
- raw_input = cli["raw_input"]
- if not "request" in cli:
- index = raw_input.find(b"\r\n\r\n")
- if index > 0:
- headers = raw_input[:index]
- data = raw_input[index + 4:]
- print("Headers: " + str(headers))
- print("Data: " + str(data))
- request = self.parseHeaders(cli, headers.decode())
- cli["request"] = request
- if "Content-Length" in request["headers"]:
- cli["length"] = request["headers"]["Content-Length"]
- cli["data"] = data
- else:
- return True
- elif "length" in cli and len(cli["data"]) < cli["length"]:
- cli["data"] += data
- if len(cli["data"]) == cli["length"]:
- return True
- def process_sock(self, cli):
- print("\r\n\r\nCREATE THREAD " + str(cli["addr"]) + " " + str(cli["request"]))
- prep = getattr(self, "preprocess", None)
- if callable(prep):
- prep(cli)
- p = Process(target=thread, args=(cli["request"], cli["response"], cli["status"], cli["type"]))
- p.start()
- cli["p"] = p
- def update(self):
- if not self.server:
- print("Server: update closed server")
- return
- readable, writeable, exceptional = select.select([self.server], [], [], 0)
- if len(readable) > 0:
- s_sock, s_addr = self.server.accept()
- if s_sock:
- s_addr = str(s_addr[0]) + ":" + str(s_addr[1])
- print("Add client " + s_addr)
- self.add(s_sock, s_addr)
- print("Clients: c: %d, r/w: %d %d %f" % (len(self.clients), len(self.readable), len(self.writeable), time.time()))
- if len(self.readable) != 0 or len(self.writeable) != 0:
- readable, writeable, exceptional = select.select(self.readable, self.writeable, [], 0)
- for sock in readable:
- cli = self.get(sock)
- data = sock.recv(128)
- if data and self.append(cli, data):
- self.readable.remove(sock)
- cli["request"]["data"] = cli["data"]
- self.process_sock(cli)
- for sock in writeable:
- print("Remove client " + self.get(sock)["addr"])
- postp = getattr(self, "postprocess", None)
- if callable(postp):
- postp(cli)
- self.remove(sock)
- to_remove = []
- for sock in self.clients:
- cli = self.clients[sock]
- if cli["status"].value != -1.0:
- print("Send " + cli["addr"] + " " + str(cli["response"].value))
- self.sendResponse(cli)
- self.writeable.append(cli["sock"])
- if time.time() > cli["timeout"]:
- to_remove.append(sock)
- for sock in to_remove:
- self.remove(sock)
- def close(self):
- if self.server:
- for sock in self.clients:
- sock = self.clients[sock]["sock"].close()
- self.server.close()
- self.readable.clear()
- self.writeable.clear()
- self.clients.clear()
- self.server = None
- if __name__ == '__main__':
- host, port = "", 9265
- print("Create HTTP server " + host + ":" + str(port))
- server = Server(host, port)
- try:
- while True:
- server.update()
- except KeyboardInterrupt:
- server.close()
- sys.exit(0)
- server.close()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement