Ainx框架实现 一

在这里插入图片描述

作者简介: 过去日记,致力于Java、GoLang,Rust等多种编程语言,热爱技术,喜欢游戏的博主。
本文收录于Ainx系列,大家有兴趣的可以看一看
相关专栏Rust初阶教程、go语言基础系列、spring教程等,大家有兴趣的可以看一看
Java并发编程系列,设计模式系列、go web开发框架 系列正在发展中,喜欢Java,GoLang,Rust,的朋友们可以关注一下哦!


本文大部分都是借鉴刘丹冰大佬的zinx框架和文章,更推荐大家去读大佬的原文,本文只是个人学习的记录

@[TOC]

初识Ainx框架

Ainx框架实现 一_第1张图片
上图就显示了所有的ainx框架的模块,我们后来将会一一实现。

Ainx-V0.1 代码实现

为了更好的看到Ainx框架,首先Ainx构建Ainx的最基本的两个模块ainterface和anet。
ainterface主要是存放一些Ainx框架的全部模块的抽象层接口类,Ainx框架的最基本的是服务类接口iserver,定义在aiface模块中。
anet模块是ainx框架中网络相关功能的实现,所有网络相关模块都会定义在anet模块中。

创建ainx框架

创建zinx文件夹,然后创建go项目

mkdir ainx
cd ./ainx
go mod init ainx

创建ainterface、anet模块

在ainx/下 创建ainterface、znet文件夹, 使当前的文件路径如下:
注意:下图由tree自动生成,要查看自己的目录也可以在命令行输入tree

└── ainx
    ├── ainterface
    │  
    └── anet

ainterface下创建服务模块抽象层iserver.go

首先我们给服务器模块抽象一个接口,因为它决定了我们整个框架入口的结构。

ainx/ainterface/iserver.go

package ainterface

//定义服务器接口
type IServer interface{
    //启动服务器方法
    Start()
    //停止服务器方法
    Stop()
    //开启业务服务方法
    Serve()
}

在anet下实现服务模块server.go

我们接下来实现我们的服务器的实体类,暂时我们给给它添加Name,IPVersion,IP,Port 四个属性,分别代表服务器的名字,服务器连接使用的ip协议,服务器绑定的IP和绑定的端口号。

ainx/anet>sever.go

package anet

import (
	"ainx/ainterface"
	"fmt"
	"net"
	"time"
)

type Server struct {
	// 设置服务器名称
	Name string
	// 设置网络协议版本
	IPVersion string
	// 设置服务器绑定IP
	IP string
	// 设置端口号
	Port string
}

//============== 实现 ainterface.IServer 里的全部接口方法 ========

// 开启网络服务
func (s *Server) Start() {
	fmt.Printf("[START] Server listenner at IP: %s, Port %s, is starting\n", s.IP, s.Port)

	// 开启一个go去做服务端的Listener业务
	go func() {
		// todo 未来目标是提供更多协议,可以利用if或者switch对IPVersion进行判断而选择采取哪种协议
		//1 获取一个TCP的Addr
		addr, err := net.ResolveTCPAddr(s.IPVersion, s.IP+":"+s.Port)
		if err != nil {
			fmt.Println("resolve tcp addr err: ", err)
			return
		}
		// 2 监听服务器地址
		listener, err := net.ListenTCP(s.IPVersion, addr)
		if err != nil {
			fmt.Println("listen", s.IPVersion, "err", err)
			return
		}
		//	  已经成功监听
		fmt.Println("start Ainx server  ", s.Name, " success, now listenning...")
		//3 启动server网络连接业务
		for {
			//3.1 阻塞等待客户端建立连接请求
			conn, err := listener.AcceptTCP()
			if err != nil {
				fmt.Println("Accept err ", err)
				continue
			}
			//3.2 TODO Server.Start() 设置服务器最大连接控制,如果超过最大连接,那么则关闭此新的连接

			//3.3 TODO Server.Start() 处理该新连接请求的 业务 方法, 此时应该有 handler 和 conn是绑定的

			//我们这里暂时做一个最大512字节的回显服务
			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 (s *Server) Stop() {
	fmt.Println("[STOP] Zinx server , name ", s.Name)
	//TODO  Server.Stop() 将其他需要清理的连接信息或者其他信息 也要一并停止或者清理
}
func (s *Server) Serve() {
	s.Start()
	//TODO Server.Serve() 是否在启动服务的时候 还要处理其他的事情呢 可以在这里添加
	//阻塞,否则主Go退出, listenner的go将会退出
	for {
		time.Sleep(10 * time.Second)
	}
}

/*
创建一个服务器句柄
*/
func NewServer(name string) ainterface.IServer {
	s := &Server{
		Name:      name,
		IPVersion: "tcp4",
		IP:        "0.0.0.0",
		Port:      "8080",
	}
	return s
}

好了,以上我们已经完成了Ainx-V0.1的基本雏形了,虽然只是一个基本的回写客户端数据,那么接下来我们就应该测试我们当前的Ainx-V0.1是否可以使用了。

Ainx框架单元测试样例

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

创建ainx/znet/server_test.go

package anet

import (
	"fmt"
	"net"
	"testing"
	"time"
)

/*
模拟客户端
*/
func ClientTest() {
	fmt.Println("Client Test ... start")
	// 3秒之后发起调用,让服务端有时间启动
	time.Sleep(3 * time.Second)
	conn, err := net.Dial("tcp", "127.0.0.1:8080")
	if err != nil {
		fmt.Println("client start err,exit")
		return
	}
	for {
		_, err := conn.Write([]byte("hello word"))
		if err != nil {
			fmt.Println("client start err,exit")
			return
		}
		buf := make([]byte, 520)
		cnt, err := conn.Read(buf)
		if err != nil {
			fmt.Println("Read buf error")
			return
		}
		fmt.Printf("Server call back : %s,cnt =%d \n ", buf[:cnt], cnt)
		time.Sleep(1 * time.Second)

	}
}

// Server 模块测试函数
func TestServer(t *testing.T) {
	/*
		服务端测试
	*/
	//
	s := NewServer("first")
	go ClientTest()
	s.Serve()
}

之后便可以运行测试程序程序进行测试
测试结果

=== RUN   TestServer
[START] Server listenner at IP: 0.0.0.0, Port 8080, is starting
Client Test ... start
start Ainx server   first  success, now listenning...
Server call back : hello word,cnt =10 
 Server call back : hello word,cnt =10 
 Server call back : hello word,cnt =10 
 Server call back : hello word,cnt =10 

你可能感兴趣的:(AINX,go,网络,golang)