解读socketserver之Tcpserver

  从代码开始,慢慢解开socketserver面纱:

import socketserver

class MyTCPHandler(socketserver.BaseRequestHandler):
    def handle(self):
        self.data = self.request.recv(1024).strip()
        print("{} wrote:".format(self.client_address[0]))
        print(self.data)
        self.request.sendall(self.data.upper())

if __name__ == "__main__":
    HOST, PORT = "localhost", 9999
    with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
        server.serve_forever()

  我们通过socketserver.TCPServer实例化对象server,那么此时应用调用类的__init__方法,前往Tcpserver类看看:

class TCPServer(BaseServer):
    address_family = socket.AF_INET
    socket_type = socket.SOCK_STREAM
    request_queue_size = 5
    allow_reuse_address = False
    def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
        BaseServer.__init__(self, server_address, RequestHandlerClass)#
        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

  看到Tcpserver的__init__方法,完成了以下几件事:

    创建套接字,绑定端口和IP,并监听

    将端口、IP和我们创建类传递到Baseserver类中;

  此时,对象的初始化工作并没有完成,接着,我们要进入baseserver类,看看该类下的__init__完成了什么工作:

class BaseServer:
    timeout = None
    def __init__(self, server_address, RequestHandlerClass):
        self.server_address = server_address #将端口和IP暂存
        self.RequestHandlerClass = RequestHandlerClass  #暂存我们创建的类
        self.__is_shut_down = threading.Event() # 创建event对象

  到此,对象的初始化工作完成。然后是调用serve_forever()方法,开始不断循环监听。下面,我们来看看,这个server_forever实现

  注意:我们要清楚一点,我们在找這个方法在哪里的时候,一定要按照顺序去找,也就是说,我们先得从子类开始找,如果子类不存在,就去其父类找。下面我们就遵循這个原则来找找看。

  先来看看父类Tcpserver:

class TCPServer(BaseServer):def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):

    def server_bind(self):
        def server_activate(self):
       def server_close(self):
def fileno(self):
 def get_request(self):
 def shutdown_request(self, request):
   def close_request(self, request):
    

  我们发现,没有server_forever方法,好,我去其继承的父类BaseServer类看看:

class BaseServer:def __init__(self, server_address, RequestHandlerClass):
        def server_activate(self):

    def serve_forever(self, poll_interval=0.5):
def shutdown(self):
        def service_actions(self):

    def handle_request(self):
      def _handle_request_noblock(self):
       def handle_timeout(self):

    def verify_request(self, request, client_address):
        def process_request(self, request, client_address):
     def server_close(self):

    def finish_request(self, request, client_address):
    def shutdown_request(self, request):
     def close_request(self, request):

    def handle_error(self, request, client_address):
def __enter__(self):
def __exit__(self, *args):

  我们发现server_forever()果然在這个类中,现在,我们的目标是:找到在什么地方调用我们自己写的handle方法。

  在我们找到的server_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)#原来底层是用epoll来实现不断循环监听
                while not self.__shutdown_request:
                    ready = selector.select(poll_interval) #有新的链接进来
                    if ready:
                        self._handle_request_noblock() # 这里应该是处理新的链接
                    self.service_actions()
        finally:
            self.__shutdown_request = False
            self.__is_shut_down.set()

  好,我大致找到了链接的处理入口,我们跟进去,继续寻找:

    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)

  到源码中,我们找到该函数,现在,只看我划线的部分。其他部分都是针对异常的处理,如果没有异常,其他都是不会执行的,所以,其他的异常处理,我们先暂时不看。

  我们发现,如果有链接,最后会交给process_request(),现在,我们继续跟进:

    def process_request(self, request, client_address):
        self.finish_request(request, client_address)
        self.shutdown_request(request)

  看到這个函数执行了两个函数,我们先到第一个finish_requset()里面看看,

    def finish_request(self, request, client_address):
        self.RequestHandlerClass(request, client_address, self)

  执行了RequestHandlerClass(request, client_address, self),這个是啥??还记得最开始我们传进来的类保存在哪呢?没错,就是RequestHandlerClass里面,现在这里才开始实例化這个类,也就是说,在这里开始调用我们自己的类了。既然是调用我们自己的类,那么必然要实例化,我们先回到自己创建的类,找找__init__方法。

class MyTCPHandler(socketserver.BaseRequestHandler):
    def handle(self):
        self.data = self.request.recv(1024).strip()
        print("{} wrote:".format(self.client_address[0]))
        print(self.data)
        self.request.sendall(self.data.upper())

  自己类没有写__init__方法,那么我去它继承的BaseRequestHandler()下面找找看:

class BaseRequestHandler:
    def __init__(self, request, client_address, server):
        self.request = request # 接受传进来的请求链接
        self.client_address = client_address  # 客户端的ip/端口
        self.server = server  #
        self.setup()
        try:
            self.handle()
        finally:
            self.finish()

    def setup(self):
        pass

    def handle(self):
        pass

    def finish(self):
        pass

  我们来看看,它继承类实例化完成了哪些操作:

    调用handle()方法,我们发现,在这个类中也有一个handle()方法,那么这里调用时调用自己写的还是這个类中的呢?

  当然是调用我们自己写!

  至此,我们完成了一次链接的完整过程!

时间: 2024-10-15 11:57:15

解读socketserver之Tcpserver的相关文章

socketserver源码解析和协程版socketserver

来,贴上一段代码让你仰慕一下欧socketserver的魅力,看欧怎么完美实现多并发的魅力 client import socket ip_port = ('127.0.0.1',8009) sk = socket.socket() sk.connect(ip_port) sk.settimeout(5) while True: data = sk.recv(1024) print('receive:',data.decode()) inp = input('please input:') sk

python SocketServer

SocketServer是标准库中一个高级别的模块,用于简化网络客户与服务器的实现.模块中,已经实现了一些可供使用的类. 在Python3中,本模块为socketserver模块.在Python 2中,本模块为SocketServer模块.所以在用import导入时,要分情况导入,否则会报错.导入的代码如下: ? 1 2 3 4 try:     import socketserver      #Python 3 except ImportError:     import SocketSer

socketserver.py代码阅读笔记

socketserver.py源码阅读笔记 前言 一直想弄清楚一个http server和Web框架的工作原理.但以我目前的实力,阅读一个http server或web框架代码还是太难了.后来又对异步IO.并发产生的兴趣.前几天做一个大作业需要写几个各种不同并发模型的TCP Server,写完才想起Python有现成的socketsever模块可以用,完全不需要自己写.于是对比了一下我写的代码和socketsever.py,发现我写的真没socketsever写的好.我的代码经验还是太少了.于是

python socket和socketserver

Python提供了两个基本的socket模块.一个是socket,它提供了标准的BSD Socket API:另一个是socketServer,它提供了服务器中心类,可以简化网络服务器的开发. 下面先简要介绍socket模块包含的类及其使用. 1.开始了解socket模块前,先熟悉下Python的网络编程模块主要支持的两种Intent协议:TCP和UDP.TCP协议是一种面向连接的可靠协议,用于建立机器之间的双向通信流.UDP协议是一种较低级别的.以数据包为基础的协议(无连接传输模式).与TCP

Python网络编程03----Python3.*中socketserver

socketserver(在Python2.*中的是SocketServer模块)是标准库中一个高级别的模块.用于简化网络客户与服务器的实现(在前面使用socket的过程中,我们先设置了socket的类型,然后依次调用bind(),listen(),accept(),最后使用while循环来让服务器不断的接受请求.而这些步骤可以通过SocketServer包来简化.).模块中,已经实现了一些可供使用的类. 我们将再次实现之前的那个基本TCP的例子.你会注意到新实现与之前有很多相似之处,但你也要注

Python使用TCPServer编写(多线程)Socket服务

SocketServer包对socket包进行了包装(封装),使得创建socket服务非常简单. TCPServer+BaseRequestHandler 使用TCPServer和BaseRequestHandler编写socket服务的样例. #-*- coding:utf-8 -*- from SocketServer import TCPServer, BaseRequestHandler import traceback class MyBaseRequestHandlerr(BaseR

SocketServer模块,hmac模块验证client合法性

hmac模块: 1.模块初识: import hmac # h = hmac.new() #括号里要给它连个bytes类型,一个是自定义的secret_key,一个是你想进行加密的bytes # 密文 = h.digest() # hmac.compare_digest() #括号内传另外一个密文,看是否相等 h = hmac.new(b'secret',b'382835896') digest = h.digest() print(digest) #>>>> b'\xa4<

Python——socketserver编程(客户端/服务器)

一.socketserver是标准库中的高级模块,它的目标是简化很多多样板代码,是创建网络客户端和服务器所必须的代码.(事件驱动) 二.模块类 BaseServer :包含核心服务器功能和mix-in类的钩子,可以用TCPServer或UDPserver创建类的实例 TCPserver/UDPserver:基础的TCP/UDP服务器 UnixStereamServer/UnixDatagramServer:基于文件的TCP/UDP服务器 ForkingMixIn/ThreadingMixIn:核

Python套接字

1.客户端/服务器架构 什么是客户端/服务器架构?对于不同的人来说,它意味着不同的东西,这取决于你问谁以及描述的是软件还是硬件系统.在这两种情况中的任何一种下,前提都很简单:服务器就是一系列硬件或软件,为一个或多个客户端(服务的用户)提供所需的"服务".它存在唯一目的就是等待客户端的请求,并响应它们(提供服务),然后等待更多请求.另一方面,客户端因特定的请求而联系服务器,并发送必要的数据,然后等待服务器的回应,最后完成请求或给出故障的原因.服务器无限地运行下去,并不断地处理请求:而客户