Python SocketServer.py

#SocketServer.py代码解析
__version__ = "0.4"


import socket
import select
import sys
import os
import errno
try:
    import threading
except ImportError:
    import dummy_threading as threading

__all__ = ["TCPServer","UDPServer","ForkingUDPServer","ForkingTCPServer",
           "ThreadingUDPServer","ThreadingTCPServer","BaseRequestHandler",
           "StreamRequestHandler","DatagramRequestHandler",
           "ThreadingMixIn", "ForkingMixIn"]
if hasattr(socket, "AF_UNIX"):
    __all__.extend(["UnixStreamServer","UnixDatagramServer",
                    "ThreadingUnixStreamServer",
                    "ThreadingUnixDatagramServer"])


#这里func函数是select.select()方法,关于select函数的作用可参见《unix环境高级编程》
def _eintr_retry(func, *args):
    """restart a system call interrupted by EINTR"""
    while True:
        try:
            return func(*args)
        except (OSError, select.error) as e:
            if e.args[0] != errno.EINTR:
                raise

class BaseServer:
    timeout = None
    
    """
    1.构造函数,self.server_address是服务器监听(IP,port)
    2.self.RequestHandlerClass
    3.self.__shutdown_request可由shutdown()方法设置为True,用来终止serv_forever()循环;
      并且调用self.__is_shut_down.set(),调用shutdown()方法的线程同时将调用self.__is_shut_down.wait()
    4:这里要说明的是,如果要使shutdown()方法起作用,那么 serve_forever()方法与shutdown()方法必须由不同的线程去
      调用,否则会导致死锁;这就要在实例化BaseServer后再创建线程
    """
    def __init__(self, server_address, RequestHandlerClass):
        """Constructor.  May be extended, do not override."""
        self.server_address = server_address
        self.RequestHandlerClass = RequestHandlerClass
        self.__is_shut_down = threading.Event()
        self.__shutdown_request = False

    """

    """
    def server_activate(self):
        """Called by constructor to activate the server.

        May be overridden.

        """
        pass


    def serve_forever(self, poll_interval=0.5):
            """
            此函数与shutdown配合着查看,这里不断循环判断self.__shutdown_request,若为False,则
            不断调用select.select函数监听self是否可读,并且select timeout时间为poll_interval

            shutdown函数会设置self.__is_shut_down为True,那么会使得serve_forever()方法内的循环终止
            """
        self.__is_shut_down.clear()
        try:
            while not self.__shutdown_request:
                # XXX: Consider using another file descriptor or
                # connecting to the socket to wake this up instead of
                # polling. Polling reduces our responsiveness to a
                # shutdown request and wastes cpu at all other times.
                r, w, e = _eintr_retry(select.select, [self], [], [],
                                       poll_interval)
                if self in r:
                    self._handle_request_noblock()
        finally:
            self.__shutdown_request = False
            self.__is_shut_down.set()

    def shutdown(self):
        """
        用来终止serv_forever的loop循环
        使用方法应该是,一个进程生成此class的的object对象,然后在某个Thread内执行object.serve_forever,然后在其他进程内调用
        object.shutdown()方法。因为在同一进程内的多个线程可以共享变量,包括python的类对象变量。
        """
        self.__shutdown_request = True
        self.__is_shut_down.wait()


    def handle_request(self):
        """
        使用select.select()方法,最终都会调用_handler_request_noblock()
        """
        # Support people who used socket.settimeout() to escape
        # handle_request before self.timeout was available.
        timeout = self.socket.gettimeout()
        if timeout is None:
            timeout = self.timeout
        elif self.timeout is not None:
            timeout = min(timeout, self.timeout)
        fd_sets = _eintr_retry(select.select, [self], [], [], timeout)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值