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
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)
    }
}

有疑问加站长微信联系(非本文作者)