#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)
Python SocketServer.py
最新推荐文章于 2022-11-29 16:51:17 发布
本文介绍了Python库中的SocketServer模块,重点讲解了TCPServer和UDPServer如何通过BaseServer的扩展实现串行、进程和线程模式。ForkingMixIN和ThreadingMixIn通过覆盖process_request方法来实现多进程和多线程。BaseRequestHandler提供了处理请求的基础结构,而StreamRequestHandler和DatagramRequestHandler进一步完善了处理函数。在UDP处理中,套接字被转换为类似文件描述符的形式进行操作。
摘要由CSDN通过智能技术生成