最近想研究一下关于长链接的相关内容,在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)和第三方库来实现类似于接口的功能。在实际开发中,我们可以根据具体需求选择合适的实现方式。
暂时使用抽象基类的形式模拟接口的实现。
在客户端和服务端交互的时候,会有一些属性需要保存,本节开发一些接口让用户可以使用存储属性。
在IConnection中定义一些接口。
@abstractmethod
def SetProperty(self, key: str, value: object):
"""
设置链接属性
:param key:
:param value:
:return:
"""
pass
@abstractmethod
def GetProperty(self, key: str) -> object:
"""
获取链接属性
:param key:
:param value:
:return:
"""
pass
@abstractmethod
def RemoveProperty(self, key: str):
"""
移除链接属性
:param key:
:param value:
:return:
"""
pass
在Connection中定义一个成员变量property,用来存放属性。
class Connection(IConnection):
def __init__(self, tcp_server: IServer, conn: socket.socket, connID: int, remote_addr: tuple, msgHandler: IMsgHandler):
self.TcpServer = tcp_server
self.Conn: socket.socket = conn # 当前链接的socket TCP套接字
self.ConnID: int = connID # 链接的ID
# self.HandlerAPI = handlerAPI # 当前链接绑定的业务处理方法的API
self.is_closed: bool = False # 链接状态
self.Remote_Addr: tuple = remote_addr # 地址
# self.Router: IRouter = router
self.msgHandler: IMsgHandler = msgHandler # 消息处理模块
self.msgQueue: Queue = Queue() # 写队列
self.property: Dict[str, object] = {}
在Connection中实现接口。
def SetProperty(self, key: str, value: object):
"""
设置链接属性
:param key:
:param value:
:return:
"""
self.property[key] = value
def GetProperty(self, key: str) -> object:
"""
获取链接属性
:param key:
:return:
"""
if key in self.property.keys():
return self.property[key]
return None
def RemoveProperty(self, key: str):
"""
移除链接属性
:param key:
:return:
"""
try:
del self.property[key]
except:
return
服务接口做完了。在demo\property中做一个客户端和服务端测试一下。
服务端代码。
# -*- 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())
con.SetProperty("PlayerID", 15)
def ConnectionStop(con):
print("======Stop========", con.GetConnID())
print("PlayerID", con.GetProperty("PlayerID"))
if __name__ == '__main__':
server = NewServer()
server.AddRouter(1, PingRouter())
server.SetOnConnStart(ConnectionStart)
server.SetOnConnStop(ConnectionStop)
server.Serve()
客户端代码与demo\msghandler一样即可。
此时发送和接收都正常。属性模块完成。
网友评论