Go语言otns源码分析
偷偷努力,悄无声息地变强,然后惊艳所有人!哈哈,小伙伴们又来学习啦~今天我将给大家介绍《Go语言otns源码分析》,这篇文章主要会讲到go语言等等知识点,不知道大家对其都有多少了解,下面我们就一起来看一吧!当然,非常希望大家能多多评论,给出合理的建议,我们一起学习,一起进步!
这篇“Go语言otns源码分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Go语言otns源码分析”文章吧。
proto文件
这个例子中只有一个proto文件,位于ot-ns-main/visualize/grpc/pb下,里面的service也只定义了两个rpc方法:
service VisualizeGrpcService {
// rpc Echo (EchoRequest) returns (EchoResponse);
rpc Visualize (VisualizeRequest) returns (stream VisualizeEvent);
rpc Command (CommandRequest) returns (CommandResponse);
}Visualize (VisualizeRequest) returns (stream VisualizeEvent)
这个方法接受一个VisualizeRequest,返回VisualizeEvent流。两个消息定义如下:
message VisualizeRequest {
}
message VisualizeEvent {
oneof type {
AddNodeEvent add_node = 1;
DeleteNodeEvent delete_node = 2;
SetNodeRloc16Event set_node_rloc16 = 3;
SetNodeRoleEvent set_node_role = 4;
SetNodePosEvent set_node_pos = 5;
SetNodePartitionIdEvent set_node_partition_id = 6;
OnNodeFailEvent on_node_fail = 7;
OnNodeRecoverEvent on_node_recover = 8;
SetParentEvent set_parent = 9;
CountDownEvent count_down = 10;
ShowDemoLegendEvent show_demo_legend = 11;
AdvanceTimeEvent advance_time = 12;
AddRouterTableEvent add_router_table = 13;
RemoveRouterTableEvent remove_router_table = 14;
AddChildTableEvent add_child_table = 15;
RemoveChildTableEvent remove_child_table = 16;
SendEvent send = 17;
SetSpeedEvent set_speed = 18;
HeartbeatEvent heartbeat = 19;
OnExtAddrChangeEvent on_ext_addr_change = 20;
SetTitleEvent set_title = 21;
SetNodeModeEvent set_node_mode = 22;
SetNetworkInfoEvent set_network_info = 23;
}
}请求为空,而VisualizeEvent里面使用oneof关键字包含了很多的消息体,每个消息体封装了一个事件。
Command (CommandRequest) returns (CommandResponse)
这个方法接受CommandRequest并返回CommandResponse,两个消息体定义如下:
message CommandRequest {
string command = 1;
}message CommandResponse {
repeated string output = 1;
}CommandResponse中的output在go中会声明为string[]
visualize/grpc/replay目录下的文件
grpcField(未包含pb)
定义了一个结构grpcField,里面包含了节点信息、当前时间与速度、标题信息、网络信息、及其设置。
type grpcField struct {
nodes map[NodeId]*grpcNode
curTime uint64
curSpeed float64
speed float64
titleInfo visualize.TitleInfo
networkInfo visualize.NetworkInfo
}grpcNode(未包含pb)
定义了节点结构grpcNode,包含各种信息,还有一个new这个结构的函数
type grpcNode struct {
nodeid NodeId
extaddr uint64
x int
y int
radioRange int
mode NodeMode
rloc16 uint16
role OtDeviceRole
partitionId uint32
failed bool
parent uint64
routerTable map[uint64]struct{}
childTable map[uint64]struct{}
}grpcServer(包含pb)
自定义了一个grpcServer,包含信息如下
type grpcServer struct {
vis *grpcVisualizer
server *grpc.Server
address string
visualizingStreams map[*grpcStream]struct{}
}同时按照接口要求实现了Visualize()和Command()方法,还自定义了其他的方法如run、stop、prepareStream等等,看名字就容易知道是什么用途
grpcStream(包含pb)
里面自定义了一个结构grpcStream,使用这个文件中的newGrpcStream可以将Visualize函数的服务端流赋到这个结构中
grpcVisualizer(包含pb)
其中自定义了一个结构:
type grpcVisualizer struct {
simctrl visualize.SimulationController
server *grpcServer
f *grpcField
showDemoLegendEvent *pb.VisualizeEvent
replay *replay.Replay
sync.Mutex
}需要注意的是这个结构继承了互斥锁
sync.Mutex,并且包含了上面的grpcServer、grpcServer结构,这个文件里面的函数大概都是添加、删除节点或者修改什么信息之类的,基本是调用了grpcField和grpcServer文件里面的函数,但是在调用之前加了锁。这个结构实现了
visualize/types.go中的Visualizer接口并且,这个结构中包含了
visualize.SimulationController接口的字段,而visualize.SimulationController定义如下:
type SimulationController interface {
Command(cmd string) ([]string, error)
}大概就是命令的入口。
cmd/otns-replay目录下的文件
grpc_Service(包含pb)
定义了
grpcService结构,并且实现了Visualize和Command两个方法
type grpcService struct {
replayFile string
}2. grpcService结构下的visualizeStream()函数
将grpcService的replay文件检验并打开,并且逐行读取内容,并解析到var entry pb.ReplayEntry中,再通过stream将entry.Event发送到服务的客户端
实现的
Visualize方法:
启动visualizeStream()协程,创建一个心跳事件,每隔一秒心跳一下,直到上面的visualizeStream()读取完成
otns_replay(包含pb)
main()函数
一系列的校验和配置参数之后,用上面的grpcService结构注册服务端,在本机地址8999端口监听。然后就是配置和打开网页
cmd/otns/otns.go文件
调用了otns_main/otns_main.go下的Main()函数:
首先依然是解析和配置参数和环境:
parseArgs()
simplelogger.SetLevel(simplelogger.ParseLevel(args.LogLevel))
parseListenAddr()
rand.Seed(time.Now().UnixNano())
// run console in the main goroutine
ctx.Defer(func() {
_ = os.Stdin.Close()
})
handleSignals(ctx)然后是打开replay文件并创建visualizer实例:
var vis visualize.Visualizer
if visualizerCreator != nil {
vis = visualizerCreator(ctx, &args)
}
visGrpcServerAddr := fmt.Sprintf("%s:%d", args.DispatcherHost, args.DispatcherPort-1)
replayFn := ""
if !args.NoReplay {
replayFn = fmt.Sprintf("otns_%s.replay", os.Getenv("PORT_OFFSET"))
}
if vis != nil {
vis = visualizeMulti.NewMultiVisualizer(
vis,
visualizeGrpc.NewGrpcVisualizer(visGrpcServerAddr, replayFn),
)
} else {
vis = visualizeGrpc.NewGrpcVisualizer(visGrpcServerAddr, replayFn)
}创建一个新模拟,并设置CmdRunner和Visualizer:
sim := createSimulation(ctx) rt := cli.NewCmdRunner(ctx, sim) sim.SetVisualizer(vis)
启动一个协程运行模拟:
go sim.Run()
启动客户命令行协程:
go func() {
err := cli.Run(rt, cliOptions)
ctx.Cancel(errors.Wrapf(err, "console exit"))
}()设置并打开网页:
go func() {
siteAddr := fmt.Sprintf("%s:%d", args.DispatcherHost, args.DispatcherPort-3)
err := webSite.Serve(siteAddr)
if err != nil {
simplelogger.Errorf("site quited: %+v, OTNS-Web won't be available!", err)
}
}()
if args.AutoGo {
go autoGo(ctx, sim)
}
web.ConfigWeb(args.DispatcherHost, args.DispatcherPort-2, args.DispatcherPort-1, args.DispatcherPort-3)
simplelogger.Debugf("open web: %v", args.OpenWeb)
if args.OpenWeb {
_ = web.OpenWeb(ctx)
}Visualizer启动:
vis.Run() // visualize must run in the main thread
simulation目录下的文件
simulation是grpcVisualizer和cmdRunner通信的桥梁。
type.go
定义了CmdRunner接口:
type CmdRunner interface {
RunCommand(cmd string, output io.Writer) error
}simulationController.go
定义了
simulationController类,这个类实现了visualize.SimulationController接口,也就是grpcVisualizer里有的字段:
type simulationController struct {
sim *Simulation
}
func (sc *simulationController) Command(cmd string) ([]string, error) {
var outputBuilder strings.Builder
sim := sc.sim
err := sim.cmdRunner.RunCommand(cmd, &outputBuilder)
if err != nil {
return nil, err
}
output := strings.Split(outputBuilder.String(), "\n")
if output[len(output)-1] == "" {
output = output[:len(output)-1]
}
return output, nil
}还定义了同样实现了
visualize.SimulationController接口的只读类,这里不展开说了。还有一个
NewSimulationController(sim *Simulation)函数产生simulationControllersimulationController应该是一个介于Command和Simulation之间的中介,接收Command并操作CmdRunner更改Simulation,并且输出信息。
simulation_config.go
定义了配置和默认配置
simulation.go
simulation结构定义:
type Simulation struct {
ctx *progctx.ProgCtx
cfg *Config
nodes map[NodeId]*Node
d *dispatcher.Dispatcher
vis visualize.Visualizer
cmdRunner CmdRunner
rawMode bool
networkInfo visualize.NetworkInfo
}有一个new产生
simulation结构的函数各种增删改查操作,都是通过
simulation结构中的visualize.Visualizer接口函数实现的
cli目录
cli目录下定义了CmdRunner及各种指令结构
ast.go
定义了各种命令结构
CmdRunner.go
定义了
CmdRunner结构:
type CmdRunner struct {
sim *simulation.Simulation
ctx *progctx.ProgCtx
contextNodeId NodeId
}实现
simulation/CmdRunner接口的RunCommand方法:
func (rt *CmdRunner) RunCommand(cmdline string, output io.Writer) error {
// run the OTNS-CLI command without node contexts
cmd := Command{}
if err := ParseBytes([]byte(cmdline), &cmd); err != nil {
if _, err := fmt.Fprintf(output, "Error: %v\n", err); err != nil {
return err
}
} else {
rt.execute(&cmd, output)
}
return nil
}在
RunCommand方法中解析配置好命令后,有各种execute...()函数来执行相应的命令,而在这些函数中又是通过调用simulation.Simulation中对应的增删改查函数来实现操作的
以上就是关于“Go语言otns源码分析”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注golang学习网行业资讯频道。
今天带大家了解了go语言的相关知识,希望对你有所帮助;关于Golang的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~
Go语言kube-scheduler之pod调度怎么实现
- 上一篇
- Go语言kube-scheduler之pod调度怎么实现
- 下一篇
- 规模扩大 10 倍,谷歌邀请更多 Gmail 和 Docs 用户测试生成式 AI
-
- Golang · Go教程 | 7分钟前 |
- Golang并发测试与goroutine性能分析
- 456浏览 收藏
-
- Golang · Go教程 | 14分钟前 |
- Go语言scanner包:位移与空格识别解析
- 213浏览 收藏
-
- Golang · Go教程 | 16分钟前 |
- Golang适配器模式与接口转换技巧
- 371浏览 收藏
-
- Golang · Go教程 | 17分钟前 |
- Golang文件备份实现教程详解
- 105浏览 收藏
-
- Golang · Go教程 | 25分钟前 |
- Golang文件上传服务器搭建教程
- 125浏览 收藏
-
- Golang · Go教程 | 26分钟前 |
- Go语言自定义类型长度限制技巧
- 161浏览 收藏
-
- Golang · Go教程 | 28分钟前 |
- Golang反射实战教程详解
- 412浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- GolangCI/CD测试流程实现详解
- 347浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Golang模块冲突解决全攻略
- 200浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Go语言处理JSON浮点数编码技巧
- 391浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Golangselect多路复用实战教程详解
- 307浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3167次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3380次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3409次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4513次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3789次使用
-
- 有关Go语言拼接URL路径的方法
- 2023-03-09 185浏览
-
- go语言能不能做后端
- 2023-03-03 460浏览
-
- go语言和java的区别是什么
- 2023-03-03 430浏览
-
- go语言如何进行强制类型转换
- 2023-03-04 450浏览
-
- go语言的beego怎么使用
- 2023-03-03 320浏览

