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