Ainx框架实现 一

在这里插入图片描述

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


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

@[TOC]

初识Ainx框架

在这里插入图片描述
上图就显示了所有的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 anetimport ("ainx/ainterface""fmt""net""time"
)type Server struct {// 设置服务器名称Name string// 设置网络协议版本IPVersion string// 设置服务器绑定IPIP 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的Addraddr, 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 anetimport ("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 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/666983.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Powershell Install 一键部署Prometheus

前言 Prometheus是一个开源的系统监控和报警系统,现在已经加入到CNCF基金会,成为继k8s之后第二个在CNCF托管的项目,在kubernetes容器管理系统中,通常会搭配prometheus进行监控,同时也支持多种exporter采集数据,还支持pushgateway进行数据上报,Prometheus性能足够支撑上…

计算机毕业设计 | vue+SpringBoot图书借阅管理系统(附源码)

1, 概述 1.1 课题背景 随着现在科学技术的进步,人类社会正逐渐走向信息化,图书馆拥有丰富的文献信息资源,是社会系统的重要组成部分,在信息社会中作用越来越重要,在我国图书馆计算机等 信息技术的应用起步…

docker安装-centos

Docker CE 支持 64 位版本 CentOS 7,并且要求内核版本不低于 3.10 卸载旧版本Docker sudo yum remove docker \ docker-common \ docker-selinux \ docker-engine使用yum安装 yum 更新到最新版本: sudo yum update执行以下命令安装依赖包: sudo yum…

PyTorch 2.2 中文官方教程(十五)

(beta)计算机视觉的量化迁移学习教程 原文:pytorch.org/tutorials/intermediate/quantized_transfer_learning_tutorial.html 译者:飞龙 协议:CC BY-NC-SA 4.0 提示 为了充分利用本教程,我们建议使用这个C…

算法刷题day05

目录 引言一、连号区间二、递增三元组三、特别数的和四、错误票据五、回文日期六、归并排序七、总结 引言 这些题其实之前是已经写过了的,但还是会有一些问题,比如说思路不清楚了,细节没有处理好,模板没有记熟都是问题&#xff0…

vue中使用html2canvas配合jspdf导出pdf(以及在导出时遇到的导出样式问题)

指定页面中导出为pdf格式并打包,使用html2canvas先转为图片格式,在利用jspdf转为pdf,最后下载打包为本地压缩包 yarn add html2canvas yarn add jspdf1. 注册一个插件并挂载 import html2Canvas from html2canvas import JsPDF from jspdf …

记一次生产系统每隔10小时(36000000毫秒)固定进行一次Full GC排查思路

一、 背景描述 某个应用在生产环境通过系统监控发现,应用每隔10小时就会触发一次Full GC,该系统当时承接的业务量并不大,而且固定10小时就会进行Full GC,通过监控时间轴发现Full GC频率很规律,直觉告诉我这不是JVM自身…

js实现根据字符串生成颜色

在JavaScript中,你可以根据给定的字符串生成一种颜色。这种操作通常需要将字符串转换为颜色代码,如十六进制颜色代码。下面是一个简单的示例,我们使用字符串的字符码来生成颜色: function stringToColor(str) {let hash 0;for (…

寒假 day1

1、请简述栈区和堆区的区别? 2、有一个整形数组:int arr[](数组的值由外部输入决定),一个整型变量: x(也 由外部输入决定)。要求: 1)删除数组中与x的值相等的元素 2)不得创建新的数组 3)最多只允许使用单层循环 4)无需考虑超出新数组长度后面的元素,所以…

nginx请求头处理

不啰嗦,直接上代码 删除Content-Type #清理Content-Type types {}设置默认的content-type default_type application/wasm; 添加请求头 add_header header_name header_value; 隐藏请求头 proxy_hide_header heade_name;

使用PyMysql模块连接mysql

PyMysql模块的安装 在命令行窗口下执行下行命令即可 linux:sudo pip3 install PyMySQL windows: pip3 install PyMysql 连接数据库并查询数据 # 导入模块 import pymysql# 与数据库建立连接 my_db pymysql.connect(host"127.0.0.1", user"root", pas…

Authentication Persistence and Session Management

翻译版本 【spring-security 6.2.1 】session-managemen Authentication Persistence and Session Management 一旦您获得了一个正在对请求进行身份验证的应用程序,就必须考虑如何在未来的请求中持久化和恢复所产生的身份验证。 默认情况下,这是自动完…

网络原理TCP/IP(4)

文章目录 面向字节流粘包问题异常情况TCP小结 面向字节流 创建⼀个TCP的socket,同时在内核中创建⼀个发送缓冲区和⼀个接收缓冲区; • 调⽤write时,数据会先写⼊发送缓冲区中; • 如果发送的字节数太⻓,会被拆分成多个TCP的数据包发出; • 如果发送的字节数太短,就会先在缓…

【lesson40】理解文件系统

文章目录 问题磁盘结构(物理)磁盘的存储结构磁盘的抽象结构 问题 1.有没有没有被打开的文件?当然有 在哪里呢?磁盘中也叫磁盘级文件 2.学习磁盘级别文件的侧重点在哪? 站在单个文件角度: 这个文件在哪里&#xff1f…

【Linux】权限管理

🔥博客主页: 小羊失眠啦. 🎥系列专栏:《C语言》 《数据结构》 《C》 《Linux》 《Cpolar》 ❤️感谢大家点赞👍收藏⭐评论✍️ 文章目录 一 、Linux中的用户1.1 Linux用户分类1.2 用户转换1.3 指令提权 二、Linux权限管…

LeetCode:88. 合并两个有序数组(双指针 Java)

目录 88. 合并两个有序数组 题目描述: 实现代码与解析: 双指针 原理思路: 88. 合并两个有序数组 题目描述: 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 num…

vscode git stash apply stash@{1}不生效

解决办法 在stash{1}前后加上引号 git stash apply “stash{1}“即可成功恢复指定的stash

企业网络采用SD-WAN的优势

近年来,SD-WAN成为企业网络领域的一项热门技术,为传统网络带来了新的变革。SD-WAN(Software Defined Wide Area Network,软件定义广域网)以其灵活性、可管理性和低成本而备受青睐。它不仅能够创建成熟的专用网络&#…

MySQL 教程 2.3

MySQL DELETE 语句 你可以使用 DELETE FROM 命令来删除 MySQL 数据表中的记录。 你可以在 mysql> 命令提示符或 PHP 脚本中执行该命令。 语法 以下是 DELETE 语句从 MySQL 数据表中删除数据的通用语法: DELETE FROM table_name WHERE condition; 参数说明&…

IP风险画像在企业网络安全中应用

随着企业数字化的不断深入,网络安全问题日益突显。IP风险画像作为一种综合性的网络安全工具,为企业提供了更全面的风险评估和防范手段。本文将结合一个实际案例,深入探讨IP风险画像在企业网络安全中的成功应用。 案例背景 一家大型金融机构…