基础的server需要如下属性和方法
- 启动服务器
- 创建addr
net.ResolveTCPAddr(s.IPVersion, fmt.Sprintf("%s:%d", s.IP, s.Port))
- 创建listener
net.ListenTCP(s.IPVersion, addr)
- 接收客户端数据
listener.AcceptTCP()
- 停止服务器
- 运行服务器
- 初始化server
- 服务名称
- tcp版本
- 监听IP
- 监听端口
go run demo/v0.1/server.go // 启动服务器
go run demo/v0.1/client.go // 启动客户端
- 启动连接 Start()
- 停止连接 Stop()
- 获取当前连接的conn对象(套接字) GetTCPConnection() *net.TCPConn
- 获取连接ID GetConnID() uint32
- 获取客户端连接的地址和端口 RemoteAddr() net.Addr
- 发送数据的方法 Send(data []byte) error
- 连接所绑定的处理业务的函数类型 type HandFunc func(*net.TCPConn, []byte, int) error
- socket TCP套接字
- 连接ID
- 当前连接的状态
- 与当前连接所绑定的处理业务方法
- 等待连接被退出的channel
将连接和数据绑定在一起
- 连接 conn ziface.IConnection
- 请求数据 data []byte
- 得到当前连接 GetConnection() IConnection
- 得到当前数据 GetData() []byte
router实际上的作用就是,服务端应用可以给Zinx框架配置当前连接的处理业务方法,之前的Zinx-V0.2我们的Zinx框架处理连接请求的方法是固定的,现在是可以自定义,并且有3种接口可以重写。
- Handle: 处理当前连接的主业务函数
- PreHandle: 如果需要在主业务函数之前有前置业务,可以重写这个方法
- PostHandle: 如果需要在主业务函数之后有后置业务,可以重写这个方法
type IRouter interface {
PreHandle(request IRequest) // 在处理conn业务之前的钩子方法
Handle(request IRequest)//在处理conn业务的方法
PostHandle(request IRequest)//在处理conn业务之后的钩子方法
}
//BaseRequest 实现router时,先嵌入这个基类,然后根据需要对这个基类的方法进行重写
type BaseRequest struct {}
// PreHandle 这里之所以BaseRouter的方法都为空,
//是因为有的Router不希望有PreHandle或PostHandle
//所以Router全部继承BaseRouter的好处是,不需要实现PreHandle和PostHandle也可以实例化
func (br *BaseRequest) PreHandle(request ziface.IRequest) {} // 在处理conn业务之前的钩子方法
func (br *BaseRequest) Handle(request ziface.IRequest) {} //在处理conn业务的方法
func (br *BaseRequest) PostHandle(request ziface.IRequest) {} //在处理conn业务之后的钩子方法
- IServer增加路由添加功能
- Server类增加Router成员
- Connection类绑定一个Router成员
- 在Connection中调用已经注册的Router处理业务
- 创建一个server句柄,使用zinxapi
- 给当前的zinx框架添加一个自定义的router,需要继承BaseRouter,实现相应的方法
- 启动server
添加全局配置
- 服务器应用/conf/zinx.json(用户进行填写)
- 创建一个Zinx的去全局配置模块utils/globalobj.go
- 读取用户配置好的zinx.json文件 --->globalobj对象中
- 提供一个全局的GlobalObject对象
- 将zinx框架中全部的硬代码,用globalobj里面的参数进行替换
- 使用zinxv0.4开发
- 消息ID
- 消息长度
- 消息内容
- 获取消息ID
- 获取消息的长度
- 获取消息的内容
- 设置消息ID
- 设置消息长度
- 设置消息内容
- 写入message的长度
- 写入message的id
- 写入message的内容
- 先读取固定长度的head-->消息内容的长度和消息的类型
- 再根据消息内容的长度,再次进行一次读取,从conn中读取消息的内容
- 将Message添加到Request属性中
- 修改连接读取数据的方式
- 给连接提供一个发包机制
我们之前在已经给Zinx配置了路由模式,但是很惨,之前的Zinx好像只能绑定一个路由的处理业务方法。显然这是无法满足基本的服务器需求的,那么现在我们要在之前的基础上,给Zinx添加多路由的方式。
- 集合-消息ID对应的router的关系map
- 根据msgID来索引调度路由方法 DoMsgHandler()
- 添加路由方法到map集合中 AddRouter()
- 将server模块中的Router属性 替换成MsgHandler属性
- 将server之前的AddRouter修改 调用MsgHandler的AddRouter
- 将connection模块Router属性 替换成MsgHandler,修改初始化Connection方法
- 修改Connection的之前调度Router的业务 替换换成MsgHandler调度,修改StartReader方法
- 添加一个Reader和Writer之间通信的channel
- 添加一个Writer Goroutine
- Reader由之前直接发送给客户端 改成发送给通信Channel
- 启动Reader和Writer一同工作
- 消息队列
- worker工作池的数量
- 创建一个worker工作池
- 根据workerPoolSize的数量去创建worker
- 每个worker都应该用go去承载
- 阻塞等待与当前worker对应的channel的消息
- 一旦有消息到来,worker应该处理当前消息对应的业务,调用MsgHandler
- 定义一个方法,将消息发送给消息队列工作池的方法
- 保证每个worker所收到的任务是均衡的,让哪个worker处理就将消息发送给对应的taskQueue即可
- 将消息发送到对应的channel
- 保证工作池只有一个,需要在启动服务的时候开启
- 在已经处理完拆包,得到request请求交给工作池来处理