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

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章 简单的链接封装和业务绑定

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 网络概念第一天 两台电脑怎么通过网络传输数据?怎样才能知道传输的是数据?谁摸过网线? 看电影,怎么看的?通过电流,...
    小吖朱阅读 5,466评论 0 1
  • # 图解TCP/IP 标签(空格分隔): 2018招聘 --- ##第1章 网络基础知识 ### ### 1.1 ...
    Kai_a3da阅读 5,327评论 0 2
  • 1.1 TCP/IP协议组 TCP/IP协议(传输控制协议)由网络层的IP协议和传输层的TCP协议组成 IP层负责...
    F麦子阅读 7,794评论 0 25
  • 什么是Socket Socket是进程通讯的一种方式,即调用这个网络库的一些API函数实现分布在不同主机的相关进程...
    onlyHalfSoul阅读 3,838评论 0 1
  • 转载 :http://www.cnblogs.com/maybe2030/p/4781555.html#_labe...
    奋斗live阅读 5,160评论 0 10