Zinx-V0.2-简单的连接封装与业务绑定
指定一个conn的处理业务
1.定义抽象IConnection
type IConnection interface {
//启动链接
Start()
//停止链接
Stop()
//获取链接ID
GetConnID() uint32
//获取conn的原生socket套接字
GetTCPConnection() *net.TCPConn
//获取远程客户端的ip地址
GetRemoteAddr() net.Addr
//发送数据给对方客户端
Send(data []byte, cnt int) error
}
定义一个处理业务的方法,这个方法在后续会被废弃掉,着这里只是便于理解流程
type HandleFunc func(*net.TCPConn,[]byte,int) error
2.实现Connection类
type Connection struct {
//当前链接的原生套接字
Conn *net.TCPConn
//链接ID
ConnID uint32
//当前的链接状态
isClosed bool
//当前链接所绑定的业务处理方法
handleAPI ziface.HandleFunc
}
/*
初始化链接方法
*/
func NewConnection(conn *net.TCPConn, connID uint32, callback_api ziface.HandleFunc) ziface.IConnection {
c := &Connection{
Conn:conn,
ConnID:connID,
handleAPI:callback_api,
isClosed:false,
}
return c
}
//针对链接读业务的方法
func (c *Connection) StartReader() {
//从对端读数据
fmt.Println("Reader go is startin....")
defer fmt.Println("connID = ", c.ConnID, "Reader is exit, remote addr is = ", c.GetRemoteAddr().String())
defer c.Stop()
for {
buf := make([]byte, 512)
cnt, err := c.Conn.Read(buf)
if err != nil {
fmt.Println("recv buf err", err)
continue
}
//将数据 传递给我们 定义好的Handle Callback方法
if err := c.handleAPI(c.Conn, buf, cnt); err != nil {
fmt.Println("ConnID", c.ConnID, "Handle is error", err)
break
}
}
}
//启动链接
func (c *Connection) Start() {
fmt.Println("Conn Start() ... id = ", c.ConnID)
//先进行读业务
go c.StartReader()
//TODO 进行写业务
}
//停止链接
func (c *Connection) Stop() {
fmt.Println("c. Stop() ... ConnId = ", c.ConnID)
//回收工作
if c.isClosed == true {
return
}
c.isClosed = true
//关闭原生套接字
_ = c.Conn.Close()
}
//获取链接ID
func (c *Connection) GetConnID() uint32 {
return c.ConnID
}
//获取conn的原生socket套接字
func (c *Connection) GetTCPConnection() *net.TCPConn {
return c.Conn
}
//获取远程客户端的ip地址
func (c *Connection) GetRemoteAddr() net.Addr {
return c.Conn.RemoteAddr()
}
//发送数据给对方客户端
func (c *Connection) Send(data []byte, cnt int) error {
if _, err := c.Conn.Write(data[:cnt]); err != nil {
fmt.Println("send buf error")
return err
}
return nil
}
在Start中进行读,在定义好的回调函数中处理写,只要改变定义好的函数就能实现不同的conn绑定不同的处理函数。
3.在Server中的改变
//定义一个 具体的回显业务 针对type HandleFunc func(*net.TCPConn,[]byte,int) error
func CallBackBusi(conn *net.TCPConn, data []byte, cnt int) error {
//回显业务
fmt.Println("【conn Handle】 CallBack..")
if _, err := conn.Write(data[:cnt]);err !=nil {
fmt.Println("write back err ", err)
return err
}
return nil
}
这里定义的函数就是上面所说的处理业务的方法
在之前的Server中改变Start中的代码,在创建完套接字conn后:
......
var cid uint32
cid = 0
for {
//3.1 阻塞等待客户端建立连接请求
conn, err := listenner.AcceptTCP()
if err != nil {
fmt.Println("Accept err ", err)
continue
}
//3.2 TODO Server.Start() 设置服务器最大连接控制,如果超过最大连接,那么则关闭此新的连接
//3.3 处理该新连接请求的 业务 方法, 此时应该有 handler 和 conn是绑定的
dealConn := NewConntion(conn, cid, CallBackToClient)
cid ++
//3.4 启动当前链接的处理业务
go dealConn.Start()
}
相当于之前Server中的读写操作放在了Connection中实现。