美文网首页
zinxv0.2 简单的链接封装和业务绑定

zinxv0.2 简单的链接封装和业务绑定

作者: 茶艺瑶 | 来源:发表于2020-04-27 16:52 被阅读0次

    这里我们需要实现的功能有以下


    image.png

    在本章中,我们需要实现的修改Server方法中的,链接处理,修改一堆代码

    go func() {
            //获取一个TCP的Addr
            addr,err := net.ResolveTCPAddr(this.IPVersion,fmt.Sprintf("%s:%d",this.IP,this.Port))
            if err!=nil{
                fmt.Println("resolve tcp addr error:",err)
            }
            //监听路由的地址
            listen,err := net.ListenTCP(this.IPVersion,addr)
            if err!=nil{
                fmt.Println("Listen",this.IPVersion,"err",err)
                return
            }
    
            fmt.Println("start zinx server succ",this.Name,"succ,Listening..")
    
            var cid uint32
            cid = 0
    
            //阻塞的等待客户端的链接,处理业务
            for {
                conn,err := listen.AcceptTCP()
                if err!=nil {
                    fmt.Println("Accept err",err)
                    continue
                }
    
                //客户端已经建立链接,做一些业务,因为比较简单,所以就回写吧
                dealConn := NewConnection(conn,cid,CallBackToClient)
                cid++
    
                //启动当前业务
                go dealConn.Start()
    
            }
        }()
    

    如果所示,我们需要一个定义一下我们的Connection基本接口

    package ziface
    
    import "net"
    
    //定义链接模块的抽象层
    type IConnection interface {
        //启动链接 让当前的链接业务开始工作
        Start()
        //停止链接
        Stop()
        //获取当前链接socket conn
        GetTCPConnection() *net.TCPConn
        //获取链接ID
        GetConnID() uint32
        //获取客户的TCP IP port
        RemoteAddr() net.Addr
        //发送数据,将数据发送远程的客户端
        Send(data []byte)
    }
    
    //定义一个处理业务的方法
    type HandleFunc func(*net.TCPConn,[]byte,int) error
    

    和一个实现链接消息处理的对象

    package znet
    
    import (
        "fmt"
        "net"
        "zinx/ziface"
    )
    
    /**
        链接模块
     */
    type Connection struct {
        //当前链接Socket TCP
        Conn *net.TCPConn
    
        //链接的ID
        ConnID uint32
    
        //当前链接的状态
        isClosed bool
    
        //当前链接的处理方法
        handleAPI ziface.HandleFunc
    
        //退出channel
        ExitChan chan bool
    }
    
    /**
        初始化方法
     */
    func NewConnection(conn *net.TCPConn,connID uint32,callback ziface.HandleFunc) *Connection {
        c:= &Connection{
            Conn:conn,
            ConnID:connID,
            handleAPI:callback,
            isClosed:false,
            ExitChan:make(chan bool,1),
        }
    
        return c
    }
    
    /**
        链接的读业务方法
     */
    func (c *Connection) StartReader()  {
        fmt.Println("Reader Goroutine is running...")
        defer fmt.Println("c.connID=",c.ConnID," Reader is exit,remote addr is ",c.RemoteAddr().String())
        defer c.Stop()
    
        for   {
            //读取客户端的数据到buf中,最大512字节
            buf :=make([]byte,512)
            cnt,err:=c.Conn.Read(buf)
            if err!=nil{
                fmt.Println("recv buf err",err)
                continue
            }
    
            //调用当前链接的所绑定的HandleApi
            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() ... ConnID = ",c.ConnID)
        //启动从当前链接的读取数据
        go c.StartReader()
        //TODO 启动从当前链接写数据的业务
    }
    
    //停止链接
    func (c *Connection) Stop(){
    
        //如果当前链接已经关闭
        if c.isClosed == true {
            return
        }
    
        c.isClosed = true
        //关闭socket链接
        c.Conn.Close()
        //回收资源
        close(c.ExitChan)
    }
    
    
    //获取当前链接socket conn
    func (c *Connection) GetTCPConnection() *net.TCPConn{
        return c.Conn
    }
    //获取链接ID
    func (c *Connection) GetConnID() uint32{
        return c.ConnID
    }
    //获取客户的TCP IP port
    func (c *Connection) RemoteAddr() net.Addr{
        return c.Conn.RemoteAddr()
    }
    //发送数据,将数据发送远程的客户端
    func (c *Connection) Send(data []byte) error {
        return nil
    }
    

    最后我们需要回到Server.go 中修改成以下代码

    package znet
    
    import (
        "errors"
        "fmt"
        "net"
        "zinx/ziface"
    )
    
    // IServer的接口实现,定义一个Server的服务器模块
    type Server struct {
        //服务器名称
        Name string
        //服务器ip版本
        IPVersion string
        //服务器监听ip
        IP string
        //端口
        Port int
    }
    
    func (this *Server) Start() {
        fmt.Printf("[Start] string Listenner at IP: %s,Prot %d,is start \n",this.IP,this.Port)
    
        //可以不阻塞
        go func() {
            //获取一个TCP的Addr
            addr,err := net.ResolveTCPAddr(this.IPVersion,fmt.Sprintf("%s:%d",this.IP,this.Port))
            if err!=nil{
                fmt.Println("resolve tcp addr error:",err)
            }
            //监听路由的地址
            listen,err := net.ListenTCP(this.IPVersion,addr)
            if err!=nil{
                fmt.Println("Listen",this.IPVersion,"err",err)
                return
            }
    
            fmt.Println("start zinx server succ",this.Name,"succ,Listening..")
    
            var cid uint32
            cid = 0
    
            //阻塞的等待客户端的链接,处理业务
            for {
                conn,err := listen.AcceptTCP()
                if err!=nil {
                    fmt.Println("Accept err",err)
                    continue
                }
    
                //客户端已经建立链接,做一些业务,因为比较简单,所以就回写吧
                dealConn := NewConnection(conn,cid,CallBackToClient)
                cid++
    
                //启动当前业务
                go dealConn.Start()
    
            }
        }()
    
    }
    
    func CallBackToClient (conn *net.TCPConn,data []byte,cnt int)  error {
        //回显的业务
        fmt.Println("[Conn Handle] CallbackToClient...")
        if _,err:=conn.Write(data[:cnt]);err!=nil{
            return  errors.New("CallBackToClient error")
        }
    
        return nil
    }
    
    
    func (this *Server) Stop() {
        //TODO 将以西服务资源,回收
    }
    
    func (this *Server) Serve() {
        //启动服务
        this.Start()
    
        //TODO 启动服务后做一些额外的业务功能
    
        //阻塞状态
        select {
    
        }
    }
    
    /**
        构造函数
     */
    func NewServer(name string) ziface.IServer  {
        s:= &Server{
            Name:name,
            IPVersion:"tcp4",
            IP:"0.0.0.0",
            Port:8999,
        }
        return  s
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

    相关文章

      网友评论

          本文标题:zinxv0.2 简单的链接封装和业务绑定

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