美文网首页
使用golang 编写一个轻量级TCP框架

使用golang 编写一个轻量级TCP框架

作者: 茶艺瑶 | 来源:发表于2020-04-27 15:47 被阅读0次
    image.png

    TCP/IP(Transmission Control Protocol/Internet Protocol) 即传输控制协议/网间协议,是一种面向连接(连接导向)的、可靠的、基于字节流的传输层(Transport layer)通信协议,因为是面向连接的协议,数据像水流一样传输,会存在黏包问题。

    我们先看看项目结构

    ├── demo
    │   └── zinxv0.1
    │       └── Server.go
    ├── go.mod
    ├── ziface
    │   └── IServer.go
    └── znet
        └── server.go
    

    我们先在定义一个Iserver.go的服务接口,我们需要启动服务器,所以在这个接口里面需要实现3个方法。

    package ziface
    
    //定义一个服务器接口
    
    type IServer interface {
        //启动服务器
        Start()
        //停止服务器
        Stop()
        //运行服务器
        Serve()
    }
    

    然后我们需要实现一个结构体来实现这个接口的定义的方法

    package znet
    
    import (
        "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..")
    
            //阻塞的等待客户端的链接,处理业务
            for {
                conn,err := listen.AcceptTCP()
                if err!=nil {
                    fmt.Println("Accept err",err)
                    continue
                }
    
                //客户端已经建立链接,做一些业务,因为比较简单,所以就回写吧
                go func() {
                    for  {
                        buf := make([]byte,512)
                        cnt,err := conn.Read(buf)
                        if err!= nil{
                            fmt.Println("recv buf err",err)
                            continue
                        }
                        //回显功能
                        if _,err:=conn.Write(buf[:cnt]); err!=nil{
                            fmt.Println("write back buf err",err)
                            continue
                        }
                    }
                }()
            }
        }()
    
    }
    
    func (this *Server) Stop() {
        //TODO 将以西服务资源,回收
    }
    
    func (this *Server) Serve() {
        //启动服务
        this.Start()
    
        //TODO 启动服务后做一些额外的业务功能
    
        //阻塞状态,因为Start()是异步的,如果不加主程式早就运行完了
        select {
    
        }
    }
    
    /**
          创建我们的服务
     */
    func NewServer(name string) ziface.IServer  {
        s:= &Server{
            Name:name,
            IPVersion:"tcp4",
            IP:"0.0.0.0",
            Port:8999,
        }
        return  s
    }
    

    后面我们在dome文件下编写我们的dome

    package main
    
    import "zinx/znet"
    
    /**
        基于Zinx框架来开发
     */
    func main()  {
        //创建一个server句柄,使用Zinx的api
        s:=znet.NewServer("[zinx v0.1]")
        //启动
        s.Serve()
    }
    
    

    客户端代码

    package main
    
    import (
        "fmt"
        "net"
        "time"
    )
    
    /**
        模拟客户端
     */
    func main()  {
        fmt.Println("client start...")
    
        time.Sleep(1 *time.Second)
    
        conn,err := net.Dial("tcp","127.0.0.1:8999")
        if err!=nil{
            fmt.Println("client start err,exit!")
            return
        }
    
        for  {
            _,err:= conn.Write([]byte("Hello Zinx v0.1"))
            if err !=nil {
                fmt.Println("write conn err",err)
                return
            }
            
            buf := make([]byte,512)
            cnt,err:=conn.Read(buf)
            if err!=nil {
                fmt.Printf("read buf error")
                return
            }
    
            fmt.Printf("server call back %s,cnt= %d\n",buf,cnt)
    
            //cpu阻塞
            time.Sleep(1*time.Second)
        }
    }
    
    

    第2章 简单的链接封装和业务绑定

    相关文章

      网友评论

          本文标题:使用golang 编写一个轻量级TCP框架

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