基本格式:
import socketserver
class MyServer(socketserver.BaseRequestHandler):
'''
重写 父类的 handle 方法,实现业务核心逻辑
'''
def handle(self):
pass
if __name__ == '__main__':
server = socketserver.ThreadingTCPServer(('192.168.0.105.',8009),MyServer)
server.serve_forever()代码示例:
class MyServer(socketserver.BaseRequestHandler):
def handle(self):
while True:
data = self.request.recv(1024).decode()
if data == 'exit':
print('连接断开')
break
print('接收到客户端{}的消息{}'.format(self.client_address,data))
res = data.upper() # 小写字母转大写
self.request.send(res.encode())
self.request.close()
if __name__ == '__main__':
server = socketserver.ThreadingTCPServer(('192.168.0.105.',8009),MyServer)
server.serve_forever()socketserver模块 源码分析:
源码分析:
'''
解析过程:
1、创建一个ThreadingTCPServer 传入的是 一个 ip,端口,+自定义的类 ,类+实例 =》走 类的init方法
2、查找init 方法:先从当前类中寻找 ThreadingTCPServer ,
当前类没有init 方法 class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass ,
从其继承的父类中查找 ThreadingMixIn 没有init 方法 ,
TCPServer 中有init 方法 ,故会执行TCPServer 类中的init 方法:
class TCPserver(BaseServer):
def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
"""Constructor. May be extended, do not override."""
# 先执行BaseServer 中的init 方法 ,
BaseServer.__init__(self, server_address, RequestHandlerClass) #相当于做了个实例变量的赋值
RequestHandlerClass 即自定义的MyServer 这个类
执行完毕 创建 socket 套接字对象
self.socket = socket.socket(self.address_family,
self.socket_type)
if bind_and_activate:
try:
self.server_bind() # 创建完对象后,绑定ip和端口
self.server_activate() #设置监听传入连接 的数量
except:
self.server_close() # 如果 绑定 和设置数量失败,则关闭当前服务端的套接字对象
raise
至此 执行完对应类的init 方法后,总共做了以下几件事情1)、创建了socket 套接字对象,2)、给这个套接字对象bind ip和端口 3)、设置监听传入连接的数量
3、猜想:创建一个完整的服务端 还需要 接收客户端连接的这个步骤 ,猜想该步骤应该在 serve_forever() 中实现
注意 不要通过 ctrl +左键的方式去查找对应的方法
要根据类的继承关系去查找!!!!!
ThreadingMixIn 中无 serve_forever
TCPServer 中无 serve_forever 但是 TCPServer 继承 BaseServer ,故要从BaseServer 中查找
经在TCPServer 父类中BaseServer 查找到 serve_forever 方法
def serve_forever(self, poll_interval=0.5):
self.__is_shut_down.clear()
try:
with _ServerSelector() as selector:
selector.register(self, selectors.EVENT_READ)
while not self.__shutdown_request:
ready = selector.select(poll_interval)
# bpo-35017: shutdown() called during select(), exit immediately.
if self.__shutdown_request:
break
if ready:
self._handle_request_noblock()
self.service_actions()
finally:
self.__shutdown_request = False
self.__is_shut_down.set()
查看 BaseServe 类中的serve_forever 方法 self._handle_request_noblock()
查找_handle_request_noblock 方法,经查 该方法在 BaseServe 中:
def _handle_request_noblock(self):
try:
request, client_address = self.get_request()
except OSError:
return
if self.verify_request(request, client_address):
try:
self.process_request(request, client_address)
except Exception:
self.handle_error(request, client_address)
self.shutdown_request(request)
except:
self.shutdown_request(request)
raise
else:
self.shutdown_request(request)
分析: request, client_address = self.get_request() 此行代码 和accept()类似 conn,address = socket.accept()
查找其 get_request ,继续从头开始找(当前对象的类继承顺序查找)
经查,在TCPserver类中查找到该方法 :
def get_request(self):
return self.socket.accept()
查看此处直接调用的socket的accept 方法,验证了上面的猜想,
返回到_handle_request_noblock 继续往下看
try:
request, client_address = self.get_request()
except OSError:
return
if self.verify_request(request, client_address):
try:
self.process_request(request, client_address)
核心:查找实现多线程相关逻辑代码
代码分析至此处已完成,1、socket 创建,2、bind ,3、listen, 4、accept ,
当前的需求是实现单个 server 同时接入多个client 处理
故还差 多线程或者多进程代码
查看上述代码 self.process_request(request, client_address) ,
查找:process_request
在 ThreadingMixIn 查找到 该方法
def process_request(self, request, client_address):
t = threading.Thread(target = self.process_request_thread,
args = (request, client_address)) #此处调用通过创建一个线程调用 process_request_thread方法执行
t.daemon = self.daemon_threads
if not t.daemon and self.block_on_close:
if self._threads is None:
self._threads = []
self._threads.append(t)
t.start()
查看发现 有创建线程去调用 process_request_thread方法
核心:发现线程 执行的是process_request_thread 方法
继续查找 process_request_thread方法:
def process_request_thread(self, request, client_address):
try:
self.finish_request(request, client_address)
except Exception:
self.handle_error(request, client_address)
finally:
self.shutdown_request(request)
通常异常捕获 ,核心代码是try里面的 ,在try中 看到finish_request 方法,
继续查找 finish_request 方法:
最终在 BaseServer 类中 查找到 finish_request
def finish_request(self, request, client_address):
self.RequestHandlerClass(request, client_address, self)
该方方法传入request 和 client_address ,然后将参数传给 RequestHandlerClass 这个类 等价于,这个类去执行init 方法
request: 历史分析中的代码中 request, client_address = self.get_request() 判断 request 就是 客户端的套接字对象 也就是conn,
client_address 就是ip和端口号
核心:发现线程执行的是 handle 方法,查找 handle()方法在哪里执行
(备注:RequestHandlerClass 就是 自定义的class MyServer(socketserver.BaseRequestHandler):) 自定义类中没有init 方法
故从父类中查找 init 方法
def __init__(self, request, client_address, server):
self.request = request
self.client_address = client_address
self.server = server
self.setup()
try:
self.handle() #父类中init 方法 执行了 handle
finally:
self.finish()
最终在 自定义类中的父类 init 方法中 执行handle 方法,而handle 方法 在 自定义类中 进行了重写,故这里子类调用的时候 执行的是当前对象类中重写的
handle 方法。
至此代码分析完成!!!!
'''
















