美文网首页
Python版本Zinx——(10)链接启动/停止自定义钩子函数

Python版本Zinx——(10)链接启动/停止自定义钩子函数

作者: 爱折腾的胖子 | 来源:发表于2023-08-29 02:21 被阅读0次

      最近想研究一下关于长链接的相关内容,在B站上看到了Zinx框架的视频,是Golang语言的框架,本着更好的理解框架的内容,按照整个Zinx课程的进度,制作一个Python版本的Zinx框架。有关于Zinx框架的具体内容,可以看框架作者的介绍
      python版本的Zinx,基于Gevent 22.10.2,使用协程功能。

      golang版本的Zinx项目,项目中两个文件夹,ziface和znet。

    • ziface主要是存放一些Zinx框架的全部模块的抽象层接口类。
    • znet模块是zinx框架中网络相关功能的实现,所有网络相关模块都会定义在znet模块中。
      └── zinx
       ├── ziface
       │  └──
       └── znet
          ├──

      python中的关键字没有interface,但是可以使用抽象基类(abstract base class)和第三方库来实现类似于接口的功能。在实际开发中,我们可以根据具体需求选择合适的实现方式。
      暂时使用抽象基类的形式模拟接口的实现。


      本节开发在链接创建之后和链接关闭之前,可以执行用户自定义的函数。
      在IServer中添加四个函数。

        @abstractmethod
        def SetOnConnStart(self, cb):
            """
            设置该Server的连接创建时Hook函数
            :param cb:
            :return:
            """
            pass
    
        @abstractmethod
        def SetOnConnStop(self, cb):
            """
            设置该Server的连接断开时的Hook函数
            :param cb:
            :return:
            """
            pass
    
        @abstractmethod
        def CallOnConnStart(self, conn: IConnection):
            """
            调用连接OnConnStart Hook函数
            :param conn:
            :return:
            """
            pass
    
        @abstractmethod
        def CallOnConnStop(self, conn: IConnection):
            """
            调用连接OnConnStop Hook函数
            :param conn:
            :return:
            """
            pass
    

      在Server创建成员变量,将钩子函数定义一下。

    class Server(IServer):
        def __init__(self, name: str, ip: str, port: int,
                     family: socket.AddressFamily = socket.AF_INET,
                     socket_kind: socket.SocketKind = socket.SOCK_STREAM):
            self.name: str = name
            self.family: socket.AddressFamily = family
            self.socket_kind: socket.SocketKind = socket_kind
            self.ip: str = ip
            self.port: int = port
            # self.Router: Optional[IRouter] = None
            self.msgHandler: IMsgHandler = NewMsgHandler()
            self.connManager: IConManager = NewConnManager()
            self.OnConnStart = None     # 函数类型  钩子函数
            self.OnConnStop = None      # 函数类型  钩子函数
    

      在Server创建函数,将钩子函数相关方法进行实现。

        def SetOnConnStart(self, cb):
            """
            设置该Server的连接创建时Hook函数
            :param cb: 函数类型
            :return:
            """
            self.OnConnStart = cb
    
        def SetOnConnStop(self, cb):
            """
            设置该Server的连接断开时的Hook函数
            :param cb:函数类型
            :return:
            """
            self.OnConnStop = cb
    
        def CallOnConnStart(self, conn: IConnection):
            """
            调用连接OnConnStart Hook函数
            :param conn:
            :return:
            """
            if self.OnConnStart:
                print("---> CallOnConnStart....")
                self.OnConnStart(conn)
    
        def CallOnConnStop(self, conn: IConnection):
            """
            调用连接OnConnStop Hook函数
            :param conn:
            :return:
            """
            if self.OnConnStop:
                print("---> CallOnConnStart....")
                self.OnConnStop(conn)
    

      在Connection中设置钩子函数的运行位置。也就是Start函数和Stop函数。

        def Start(self):
            """
            启动链接 让当前的链接准备开始工作
            :return:
            """
            print("链接开启,ID=", self.ConnID)
            # 开启写业务
            g1 = gevent.spawn(self.StartWriter)
            # 开启读业务
            g2 = gevent.spawn(self.StartReader)
            GlobalGevents.append(g1)
            GlobalGevents.append(g2)
            # 按照用户传递进来的创建连接时需要处理的业务,执行钩子方法
            self.TcpServer.CallOnConnStart(self)
    
        def Stop(self):
            """
            停止链接 结束当前链接的工作
            :return:
            """
            print("链接关闭,ID=", self.ConnID)
            if self.is_closed:
                return
            self.is_closed = True
    
            # 如果用户注册了该链接的关闭回调业务,那么在此刻应该显示调用
            self.TcpServer.CallOnConnStop(self)
            # 关闭socket链接,回收资源
            self.Conn.close()
            # 将链接从连接管理器中删除
            self.TcpServer.GetConnMgr().Remove(self)
    

      服务接口做完了。在demo\hook中做一个客户端和服务端测试一下。
      服务端代码。

    # -*- coding: utf-8 -*-
    import sys
    
    sys.path.append("../../")
    from znet.server import NewServer
    from znet.router import BaseRouter
    from ziface.irequest import IRequest
    
    
    class PingRouter(BaseRouter):
        """
        用户自定义路由
        """
    
        def __init__(self):
            super().__init__()
    
        def Handle(self, request: IRequest):
            """
            处理conn业务的方法
            :param request:
            :return:
            """
            try:
                print("调用Handle")
                # request.GetConnection().GetTCPConnection().send("ping\n".encode("GB2312"))
                print(request.GetData())
                request.GetConnection().SendMsg(1, "ping\n".encode("GB2312"))
                request.GetConnection().SendMsg(1, request.GetData())
            except Exception as e:
                print("ping异常", e)
    
    
    def ConnectionStart(con):
        print("======Start========", con.GetConnID())
    
    
    def ConnectionStop(con):
        print("======Stop========", con.GetConnID())
    
    
    if __name__ == '__main__':
        server = NewServer()
        server.AddRouter(1, PingRouter())
        server.SetOnConnStart(ConnectionStart)
        server.SetOnConnStop(ConnectionStop)
        server.Serve()
    
    

      客户端代码与demo\msghandler一样即可。
      此时发送和接收都正常。钩子模块完成。

    相关文章

      网友评论

          本文标题:Python版本Zinx——(10)链接启动/停止自定义钩子函数

          本文链接:https://www.haomeiwen.com/subject/uodmmdtx.html