采用Python實現的異步TCP服務器
這是一個采用Python編寫的非常基本的異步套接字socket服務器。
import socket import selectclass Client(object): def init(self, addr, sock): self._socket = sock self._backlog = b'' self.done = False
def read(self, data): """ This function is meant to be overloaded by classes inheriting from Client. It's executed whenever something is received from the client. """ ss = data.decode('utf-8', 'replace') for s in ss.strip().split('\n'): if s == "hello": self.write("Hello, World!\n") def write(self, data): self._backlog += bytearray(data, 'utf-8') def _read_ready(self): """ Since sockets only allow for reading a specified amount of bytes we can set the socket to not block on empty recv and continue receiving until the call fails. There by receiving more than the specified amount. """ data = b'' self._socket.setblocking(False) while True: try: r = self._socket.recv(100) data += r except (socket.timeout, socket.error): break self._socket.setblocking(True) if not r: self.done = True return self.read(data) def _write_ready(self): """ We only write things to the socket when it signals that it's ready to receive something. Not doing this an relying on implicit buffers works most of the time but this really isn't a difficult thing to implement. """ if self._backlog: count = self._socket.send(self._backlog) self._backlog = self._backlog[count:]
def main_loop(): sock = socket.socket() sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind(("", 8002)) sock.listen(1) # listen(1) means that we only allow new
# connections when the previous ones have # been properly processed. clients = {} # Keep a dictionary mapping sockets to clients try: while True: # We add `sock` to the `rlist` since it will signal # that it's ready to be read when a new connection is # waiting to be accepted. rlist = [sock] + list(clients.keys()) wlist = [s for (s, c) in clients.items() if c._backlog] (rs, ws, _) = select.select(rlist, wlist, []) try: for r in rs: if r == sock: (s, addr) = sock.accept() clients[s] = Client(addr, s) elif r in clients: clients[r]._read_ready() for w in ws: if w in clients: clients[w]._write_ready() except Exception: # Including this catch as an example. It's often # nice to handle this and then break from the loop. raise # Iterate over all the clients to find out which ones # the client has disconnected from so we can remove # their references and let them be collected. for s in list(clients.keys())[:]: if clients[s].done: del clients[s] sock.listen(1) except KeyboardInterrupt: print("Got CTRL-C, quitting") finally: sock.close()</pre><br />
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!