101 lines
2.3 KiB
Go
101 lines
2.3 KiB
Go
package znet
|
||
|
||
import (
|
||
"fmt"
|
||
"go-study/zinx/ziface"
|
||
"net"
|
||
)
|
||
|
||
type Server struct {
|
||
// Name 服务器名称
|
||
Name string
|
||
// IPVersion tcp4 or tcp6
|
||
IPVersion string
|
||
// IP 服务器监听的 IP
|
||
IP string
|
||
// Port 服务器监听的端口
|
||
Port int
|
||
}
|
||
|
||
// NewServer 创建一个服务器句柄
|
||
func NewServer(name string) ziface.IServer {
|
||
return &Server{
|
||
Name: name,
|
||
IPVersion: "tcp4",
|
||
IP: "0.0.0.0",
|
||
Port: 7777,
|
||
}
|
||
}
|
||
|
||
// Start 启动服务器
|
||
func (s *Server) Start() {
|
||
fmt.Printf("[START] Server listenner at IP: %s, Port %d, is starting\n", s.IP, s.Port)
|
||
|
||
go func() {
|
||
// 1. 获取一个 TCP 的 Addr
|
||
addr, err := net.ResolveTCPAddr(s.IPVersion, fmt.Sprintf("%s:%d", s.IP, s.Port))
|
||
if err != nil {
|
||
fmt.Println("resolve tcp addr error:", err)
|
||
return
|
||
}
|
||
|
||
// 2. 监听服务器地址
|
||
listener, err := net.ListenTCP(s.IPVersion, addr)
|
||
if err != nil {
|
||
fmt.Println("listen", s.IPVersion, "err", err)
|
||
return
|
||
}
|
||
|
||
fmt.Println("start Zinx server ", s.Name, " succ, now listening...")
|
||
|
||
// TODO 应该有一个自动生成 ID 的方法
|
||
cid := uint32(0)
|
||
|
||
// 3. 阻塞等待客户端连接,处理客户端连接业务(读写)
|
||
for {
|
||
// 3.1 阻塞等待客户端连接,AcceptTCP 会阻塞
|
||
conn, err := listener.AcceptTCP()
|
||
if err != nil {
|
||
fmt.Println("Accept err", err)
|
||
continue
|
||
}
|
||
|
||
// 3.2 TODO 设置服务器最大连接数,如果超过最大连接数则关闭此新连接
|
||
|
||
// 3.3 处理该新连接请求的业务方法,此时 handler 和 conn 应该是绑定的
|
||
dealConn := NewConnection(conn, cid, CallbackToClient)
|
||
cid++
|
||
|
||
// 3.4 启动当前连接的业务处理
|
||
go dealConn.Start()
|
||
}
|
||
}()
|
||
}
|
||
|
||
// Stop 停止服务器
|
||
func (s *Server) Stop() {
|
||
fmt.Println("[STOP] Zinx server, name ", s.Name)
|
||
|
||
// TODO 将需要清理的连接信息或者其他信息一并停止或者清理
|
||
}
|
||
|
||
// Serve 运行服务器
|
||
func (s *Server) Serve() {
|
||
s.Start()
|
||
|
||
// TODO 做一些启动服务器之后的额外业务
|
||
|
||
// 阻塞,否则主 Go 程退出,listener 会退出
|
||
select {}
|
||
}
|
||
|
||
// CallbackToClient 定义当前客户端连接的业务处理方法
|
||
func CallbackToClient(conn *net.TCPConn, data []byte, cnt int) error {
|
||
// 回显业务
|
||
if _, err := conn.Write(data[:cnt]); err != nil {
|
||
fmt.Println("write back buf err", err)
|
||
return fmt.Errorf("CallbackToClient error: %v", err)
|
||
}
|
||
return nil
|
||
}
|