socketserver 源码阅读与分析

首先看到文件上半部分的注释,讲清楚了这个module里的类继承关系。

+------------+
| BaseServer |
+------------+
        |
        v
+-----------+        +------------------+
| TCPServer |------->| UnixStreamServer |
+-----------+        +------------------+
        |
        v
+-----------+        +--------------------+
| UDPServer |------->| UnixDatagramServer |
+-----------+        +--------------------+

不在上面描述的有线程和进程模型,它们是通过Mixin实现的。一个同步的服务器基本上 就是以下这样的套路:

import socket

sock = socket.socket()
sock.bind(('localhost', 8080))
sock.listen()


def handle(conn, client_addr):
    conn.send(b"some data")
    conn.close()


while True:
    conn, client_addr = sock.accept()
    handle(conn, client_addr)

socketserver 也不例外,虽然里面用到了 selectors.PollSelector,这个文件里最精彩 的部分在于实现 ThreadingMixInForkingMixIn。我也来写一个更简单的版本:

import socket
import threading
import selectors


class BaseServer:
    def __init__(self):
        self.selector = selectors.PollSelector()

    def fileno(self):
        raise NotImplemented()

    def handle_request(self):
        raise NotImplemented()

    def serve_forever(self):
        self.selector.register(self, selectors.EVENT_READ)

        while True:
            if self.selector.select():
                self.handle_request()


class TCPServer(BaseServer):
    def __init__(self):
        super().__init__()
        self.socket = socket.socket()
        self.socket.bind(('localhost', 8080))
        self.socket.listen()

    def fileno(self):
        return self.socket.fileno()

    def handle_request(self):
        return self.__handle_request()

    def _handle_request(self):
        conn, addr = self.socket.accept()
        conn.send(b'hello world\n')
        conn.close()


class ThreadingMixIn:
    def handle_request(self):
        t = threading.Thread(
            target=self._handle_request,
        )
        t.start()


class ThreadingTCPServer(ThreadingMixIn, TCPServer):
    pass


if __name__ == "__main__":
    # TCPServer().serve_forever()
    ThreadingTCPServer().serve_forever()

更多文章
  • 读《系统之美:决策者的系统思考》
  • Linux高分屏支持
  • GCC默认的头文件搜索路径
  • 读《远见-如何规划职业生涯3大阶段》
  • 后端工程师学前端(五): SASS
  • 后端工程师学前端(四): CSS进阶(盒子模型)
  • 读《投资中最简单的事》
  • 后端工程师学前端(三): CSS进阶(特指度、单位和字体族)
  • 后端工程师学前端(二): CSS基础知识(规则与选择器)
  • Swift语法笔记
  • 读《管理的实践》
  • 后端工程师学前端(一): HTML
  • frp 源码阅读与分析(二):TCP内网穿透的实现
  • 五天不用微信 - 爽得很
  • frp 源码阅读与分析(一):流程和概念