• 1. Zinx-V0.1-基础Server
    • 1.1 Zinx-V0.1 代码实现
      • A) 创建zinx框架
      • B) 创建ziface、znet模块
      • C) 在ziface下创建服务模块抽象层iserver.go
      • D) 在znet下实现服务模块server.go
    • 1.2 Zinx框架单元测试样例
    • 1.3 使用Zinx-V0.1完成应用程序

    1. Zinx-V0.1-基础Server

    为了更好的看到Zinx框架,首先Zinx构建Zinx的最基本的两个模块zifaceznet

    ziface主要是存放一些Zinx框架的全部模块的抽象层接口类,Zinx框架的最基本的是服务类接口iserver,定义在ziface模块中。

    znet模块是zinx框架中网络相关功能的实现,所有网络相关模块都会定义在znet模块中。

    1.1 Zinx-V0.1 代码实现

    A) 创建zinx框架

    在$GOPATH/src下创建zinx文件夹

    B) 创建ziface、znet模块

    在zinx/下 创建ziface、znet文件夹, 使当前的文件路径如下:

    1. └── zinx
    2. ├── ziface
    3. └──
    4. └── znet
    5. ├──
    C) 在ziface下创建服务模块抽象层iserver.go

    zinx/ziface/iserver.go

    1. package ziface
    2. //定义服务器接口
    3. type IServer interface{
    4. //启动服务器方法
    5. Start()
    6. //停止服务器方法
    7. Stop()
    8. //开启业务服务方法
    9. Serve()
    10. }
    D) 在znet下实现服务模块server.go
    1. package znet
    2. import (
    3. "fmt"
    4. "net"
    5. "time"
    6. "zinx/ziface"
    7. )
    8. //iServer 接口实现,定义一个Server服务类
    9. type Server struct {
    10. //服务器的名称
    11. Name string
    12. //tcp4 or other
    13. IPVersion string
    14. //服务绑定的IP地址
    15. IP string
    16. //服务绑定的端口
    17. Port int
    18. }
    19. //============== 实现 ziface.IServer 里的全部接口方法 ========
    20. //开启网络服务
    21. func (s *Server) Start() {
    22. fmt.Printf("[START] Server listenner at IP: %s, Port %d, is starting\n", s.IP, s.Port)
    23. //开启一个go去做服务端Linster业务
    24. go func() {
    25. //1 获取一个TCP的Addr
    26. addr, err := net.ResolveTCPAddr(s.IPVersion, fmt.Sprintf("%s:%d", s.IP, s.Port))
    27. if err != nil {
    28. fmt.Println("resolve tcp addr err: ", err)
    29. return
    30. }
    31. //2 监听服务器地址
    32. listenner, err:= net.ListenTCP(s.IPVersion, addr)
    33. if err != nil {
    34. fmt.Println("listen", s.IPVersion, "err", err)
    35. return
    36. }
    37. //已经监听成功
    38. fmt.Println("start Zinx server ", s.Name, " succ, now listenning...")
    39. //3 启动server网络连接业务
    40. for {
    41. //3.1 阻塞等待客户端建立连接请求
    42. conn, err := listenner.AcceptTCP()
    43. if err != nil {
    44. fmt.Println("Accept err ", err)
    45. continue
    46. }
    47. //3.2 TODO Server.Start() 设置服务器最大连接控制,如果超过最大连接,那么则关闭此新的连接
    48. //3.3 TODO Server.Start() 处理该新连接请求的 业务 方法, 此时应该有 handler 和 conn是绑定的
    49. //我们这里暂时做一个最大512字节的回显服务
    50. go func () {
    51. //不断的循环从客户端获取数据
    52. for {
    53. buf := make([]byte, 512)
    54. cnt, err := conn.Read(buf)
    55. if err != nil {
    56. fmt.Println("recv buf err ", err)
    57. continue
    58. }
    59. //回显
    60. if _, err := conn.Write(buf[:cnt]); err !=nil {
    61. fmt.Println("write back buf err ", err)
    62. continue
    63. }
    64. }
    65. }()
    66. }
    67. }()
    68. }
    69. func (s *Server) Stop() {
    70. fmt.Println("[STOP] Zinx server , name " , s.Name)
    71. //TODO Server.Stop() 将其他需要清理的连接信息或者其他信息 也要一并停止或者清理
    72. }
    73. func (s *Server) Serve() {
    74. s.Start()
    75. //TODO Server.Serve() 是否在启动服务的时候 还要处理其他的事情呢 可以在这里添加
    76. //阻塞,否则主Go退出, listenner的go将会退出
    77. for {
    78. time.Sleep(10*time.Second)
    79. }
    80. }
    81. /*
    82. 创建一个服务器句柄
    83. */
    84. func NewServer (name string) ziface.IServer {
    85. s:= &Server {
    86. Name :name,
    87. IPVersion:"tcp4",
    88. IP:"0.0.0.0",
    89. Port:7777,
    90. }
    91. return s
    92. }

    好了,以上我们已经完成了Zinx-V0.1的基本雏形了,虽然只是一个基本的回写客户端数据(我们之后会自定义处理客户端业务方法),那么接下来我们就应该测试我们当前的zinx-V0.1是否可以使用了。

    1.2 Zinx框架单元测试样例

    理论上我们应该可以现在导入zinx框架,然后写一个服务端程序,再写一个客户端程序进行测试,但是我们可以通过Go的单元Test功能,进行单元测试

    创建zinx/znet/server_test.go

    1. package znet
    2. import (
    3. "fmt"
    4. "net"
    5. "testing"
    6. "time"
    7. )
    8. /*
    9. 模拟客户端
    10. */
    11. func ClientTest() {
    12. fmt.Println("Client Test ... start")
    13. //3秒之后发起测试请求,给服务端开启服务的机会
    14. time.Sleep(3 * time.Second)
    15. conn,err := net.Dial("tcp", "127.0.0.1:7777")
    16. if err != nil {
    17. fmt.Println("client start err, exit!")
    18. return
    19. }
    20. for {
    21. _, err := conn.Write([]byte("hello ZINX"))
    22. if err !=nil {
    23. fmt.Println("write error err ", err)
    24. return
    25. }
    26. buf :=make([]byte, 512)
    27. cnt, err := conn.Read(buf)
    28. if err != nil {
    29. fmt.Println("read buf error ")
    30. return
    31. }
    32. fmt.Printf(" server call back : %s, cnt = %d\n", buf, cnt)
    33. time.Sleep(1*time.Second)
    34. }
    35. }
    36. //Server 模块的测试函数
    37. func TestServer(t *testing.T) {
    38. /*
    39. 服务端测试
    40. */
    41. //1 创建一个server 句柄 s
    42. s := NewServer("[zinx V0.1]")
    43. /*
    44. 客户端测试
    45. */
    46. go ClientTest()
    47. //2 开启服务
    48. s.Serve()
    49. }

    在zinx/znet下执行

    1. $ go test

    执行结果,如下:

    1. [START] Server listenner at IP: 0.0.0.0, Port 7777, is starting
    2. Client Test ... start
    3. listen tcp4 err listen tcp4 0.0.0.0:7777: bind: address already in use
    4. server call back : hello ZINX, cnt = 6
    5. server call back : hello ZINX, cnt = 6
    6. server call back : hello ZINX, cnt = 6
    7. server call back : hello ZINX, cnt = 6

    说明我们的zinx框架已经可以使用了。

    1.3 使用Zinx-V0.1完成应用程序

    当然,如果感觉go test 好麻烦,那么我们可以完全基于zinx写两个应用程序,Server.go , Client.go

    Server.go

    1. package main
    2. import (
    3. "zinx/znet"
    4. )
    5. //Server 模块的测试函数
    6. func main() {
    7. //1 创建一个server 句柄 s
    8. s := znet.NewServer("[zinx V0.1]")
    9. //2 开启服务
    10. s.Serve()
    11. }

    启动Server.go

    1. go run Server.go

    Client.go

    1. package main
    2. import (
    3. "fmt"
    4. "net"
    5. "time"
    6. )
    7. func main() {
    8. fmt.Println("Client Test ... start")
    9. //3秒之后发起测试请求,给服务端开启服务的机会
    10. time.Sleep(3 * time.Second)
    11. conn,err := net.Dial("tcp", "127.0.0.1:7777")
    12. if err != nil {
    13. fmt.Println("client start err, exit!")
    14. return
    15. }
    16. for {
    17. _, err := conn.Write([]byte("hahaha"))
    18. if err !=nil {
    19. fmt.Println("write error err ", err)
    20. return
    21. }
    22. buf :=make([]byte, 512)
    23. cnt, err := conn.Read(buf)
    24. if err != nil {
    25. fmt.Println("read buf error ")
    26. return
    27. }
    28. fmt.Printf(" server call back : %s, cnt = %d\n", buf, cnt)
    29. time.Sleep(1*time.Second)
    30. }
    31. }

    启动Client.go进行测试

    1. go run Client.go