欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go語(yǔ)言學(xué)習(xí)otns示例分析

 更新時(shí)間:2023年04月23日 14:20:32   作者:LiP  
這篇文章主要為大家介紹了Go語(yǔ)言學(xué)習(xí)otns示例分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

學(xué)習(xí)過(guò)程

由于在用虛擬機(jī)體驗(yàn)過(guò)程中出現(xiàn)了未知的錯(cuò)誤之后,打算使用wsl又遇到了安裝錯(cuò)誤,各種辦法解決無(wú)果,于是我打算跳過(guò)體驗(yàn)的這一部分,直接先進(jìn)行這個(gè)例子中的grpc調(diào)用部分的梳理分析,等有空了再去解決一下wsl安裝不了的問(wèn)題。

proto文件

這個(gè)例子中只有一個(gè)proto文件,位于ot-ns-main/visualize/grpc/pb下,里面的service也只定義了兩個(gè)rpc方法:

service VisualizeGrpcService {
    //    rpc Echo (EchoRequest) returns (EchoResponse);
    rpc Visualize (VisualizeRequest) returns (stream VisualizeEvent);
    rpc Command (CommandRequest) returns (CommandResponse);
}
  • Visualize (VisualizeRequest) returns (stream VisualizeEvent)

這個(gè)方法接受一個(gè)VisualizeRequest,返回VisualizeEvent流。兩個(gè)消息定義如下:

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;
    }
}

請(qǐng)求為空,而VisualizeEvent里面使用oneof關(guān)鍵字包含了很多的消息體,每個(gè)消息體封裝了一個(gè)事件。

  • Command (CommandRequest) returns (CommandResponse)

這個(gè)方法接受CommandRequest并返回CommandResponse,兩個(gè)消息體定義如下:

message CommandRequest {
    string command = 1;
}
message CommandResponse {
    repeated string output = 1;
}

CommandResponse中的output在go中會(huì)聲明為string[]

visualize/grpc/replay目錄下的文件

  • grpcField(未包含pb)

定義了一個(gè)結(jié)構(gòu)grpcField,里面包含了節(jié)點(diǎn)信息、當(dāng)前時(shí)間與速度、標(biāo)題信息、網(wǎng)絡(luò)信息、及其設(shè)置。

type grpcField struct {
   nodes       map[NodeId]*grpcNode
   curTime     uint64
   curSpeed    float64
   speed       float64
   titleInfo   visualize.TitleInfo
   networkInfo visualize.NetworkInfo
}
  • grpcNode(未包含pb)

定義了節(jié)點(diǎn)結(jié)構(gòu)grpcNode,包含各種信息,還有一個(gè)new這個(gè)結(jié)構(gòu)的函數(shù)

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)

自定義了一個(gè)grpcServer,包含信息如下

type grpcServer struct {
   vis                *grpcVisualizer
   server             *grpc.Server
   address            string
   visualizingStreams map[*grpcStream]struct{}
}

同時(shí)按照接口要求實(shí)現(xiàn)了Visualize()Command()方法,還自定義了其他的方法如runstop、prepareStream等等,看名字就容易知道是什么用途

  • grpcStream(包含pb)

里面自定義了一個(gè)結(jié)構(gòu)grpcStream,使用這個(gè)文件中的newGrpcStream可以將Visualize函數(shù)的服務(wù)端流賦到這個(gè)結(jié)構(gòu)中

  • grpcVisualizer(包含pb)

其中自定義了一個(gè)結(jié)構(gòu):

    type grpcVisualizer struct {
       simctrl             visualize.SimulationController
       server              *grpcServer
       f                   *grpcField
       showDemoLegendEvent *pb.VisualizeEvent
       replay              *replay.Replay
       sync.Mutex
    }
  • 需要注意的是這個(gè)結(jié)構(gòu)繼承了互斥鎖sync.Mutex,并且包含了上面的grpcServer、grpcServer結(jié)構(gòu),這個(gè)文件里面的函數(shù)大概都是添加、刪除節(jié)點(diǎn)或者修改什么信息之類(lèi)的,基本是調(diào)用了grpcFieldgrpcServer文件里面的函數(shù),但是在調(diào)用之前加了鎖。
  • 這個(gè)結(jié)構(gòu)實(shí)現(xiàn)了visualize/types.go中的Visualizer接口
  • 并且,這個(gè)結(jié)構(gòu)中包含了visualize.SimulationController接口的字段,而visualize.SimulationController定義如下:
type SimulationController interface {
    Command(cmd string) ([]string, error)
}

大概就是命令的入口。

cmd/otns-replay目錄下的文件

grpc_Service(包含pb)

  • 定義了grpcService結(jié)構(gòu),并且實(shí)現(xiàn)了VisualizeCommand兩個(gè)方法
type grpcService struct {
   replayFile string
}

2. grpcService結(jié)構(gòu)下的visualizeStream()函數(shù)

grpcService的replay文件檢驗(yàn)并打開(kāi),并且逐行讀取內(nèi)容,并解析到var entry pb.ReplayEntry中,再通過(guò)stream將entry.Event發(fā)送到服務(wù)的客戶(hù)端

  • 實(shí)現(xiàn)的Visualize方法:

啟動(dòng)visualizeStream()協(xié)程,創(chuàng)建一個(gè)心跳事件,每隔一秒心跳一下,直到上面的visualizeStream()讀取完成

otns_replay(包含pb)

main()函數(shù)

一系列的校驗(yàn)和配置參數(shù)之后,用上面的grpcService結(jié)構(gòu)注冊(cè)服務(wù)端,在本機(jī)地址8999端口監(jiān)聽(tīng)。然后就是配置和打開(kāi)網(wǎng)頁(yè)

cmd/otns/otns.go文件

調(diào)用了otns_main/otns_main.go下的Main()函數(shù):

首先依然是解析和配置參數(shù)和環(huán)境:

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)

然后是打開(kāi)replay文件并創(chuàng)建visualizer實(shí)例:

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)
}

創(chuàng)建一個(gè)新模擬,并設(shè)置CmdRunnerVisualizer

sim := createSimulation(ctx)
rt := cli.NewCmdRunner(ctx, sim)
sim.SetVisualizer(vis)

啟動(dòng)一個(gè)協(xié)程運(yùn)行模擬:

go sim.Run()

啟動(dòng)客戶(hù)命令行協(xié)程:

go func() {
   err := cli.Run(rt, cliOptions)
   ctx.Cancel(errors.Wrapf(err, "console exit"))
}()

設(shè)置并打開(kāi)網(wǎng)頁(yè):

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啟動(dòng):

vis.Run() // visualize must run in the main thread

simulation目錄下的文件

simulationgrpcVisualizercmdRunner通信的橋梁。

type.go

定義了CmdRunner接口:

type CmdRunner interface {
   RunCommand(cmd string, output io.Writer) error
}

simulationController.go

  • 定義了simulationController類(lèi),這個(gè)類(lèi)實(shí)現(xiàn)了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
}
  • 還定義了同樣實(shí)現(xiàn)了visualize.SimulationController接口的只讀類(lèi),這里不展開(kāi)說(shuō)了。
  • 還有一個(gè)NewSimulationController(sim *Simulation)函數(shù)產(chǎn)生simulationController
  • simulationController應(yīng)該是一個(gè)介于Command和Simulation之間的中介,接收Command并操作CmdRunner更改Simulation,并且輸出信息。

simulation_config.go

定義了配置和默認(rèn)配置

simulation.go

  • simulation結(jié)構(gòu)定義:
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
}
  • 有一個(gè)new產(chǎn)生simulation結(jié)構(gòu)的函數(shù)
  • 各種增刪改查操作,都是通過(guò)simulation結(jié)構(gòu)中的visualize.Visualizer接口函數(shù)實(shí)現(xiàn)的

cli目錄

cli目錄下定義了CmdRunner及各種指令結(jié)構(gòu)

ast.go

定義了各種命令結(jié)構(gòu)

CmdRunner.go

  • 定義了CmdRunner結(jié)構(gòu):
type CmdRunner struct {
   sim           *simulation.Simulation
   ctx           *progctx.ProgCtx
   contextNodeId NodeId
}
  • 實(shí)現(xiàn)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...()函數(shù)來(lái)執(zhí)行相應(yīng)的命令,而在這些函數(shù)中又是通過(guò)調(diào)用simulation.Simulation中對(duì)應(yīng)的增刪改查函數(shù)來(lái)實(shí)現(xiàn)操作的

總結(jié)

以上就是Go語(yǔ)言學(xué)習(xí)otns示例分析的詳細(xì)內(nèi)容,更多關(guān)于Go語(yǔ)言otns示例的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Golang: 內(nèi)建容器的用法

    Golang: 內(nèi)建容器的用法

    這篇文章主要介紹了Golang: 內(nèi)建容器的用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-05-05
  • Go語(yǔ)言中數(shù)組的基本用法演示

    Go語(yǔ)言中數(shù)組的基本用法演示

    這篇文章主要介紹了Go語(yǔ)言中數(shù)組的基本用法演示,包括一個(gè)冒泡排序算法的簡(jiǎn)單實(shí)現(xiàn),需要的朋友可以參考下
    2015-10-10
  • Go語(yǔ)言使用GORM操作數(shù)據(jù)庫(kù)使用指南

    Go語(yǔ)言使用GORM操作數(shù)據(jù)庫(kù)使用指南

    GORM(全稱(chēng)為Go?Object?Relational?Mapping)是一個(gè)在Go語(yǔ)言中使用的輕量級(jí)的對(duì)象關(guān)系映射(ORM)庫(kù),本文主要為大家介紹了GORM操作數(shù)據(jù)庫(kù)具體方法,需要的可以參考一下
    2023-05-05
  • Go實(shí)現(xiàn)文件上傳和下載

    Go實(shí)現(xiàn)文件上傳和下載

    這篇文章主要為大家詳細(xì)介紹了Go實(shí)現(xiàn)文件上傳和下載,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • go使用net/url包來(lái)解析URL提取主機(jī)部分

    go使用net/url包來(lái)解析URL提取主機(jī)部分

    這篇文章主要為大家介紹了go使用net/url包來(lái)解析URL提取主機(jī)部分實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • Golang?sync.Once實(shí)現(xiàn)單例模式的方法詳解

    Golang?sync.Once實(shí)現(xiàn)單例模式的方法詳解

    Go?語(yǔ)言的?sync?包提供了一系列同步原語(yǔ),其中?sync.Once?就是其中之一。本文將深入探討?sync.Once?的實(shí)現(xiàn)原理和使用方法,幫助大家更好地理解和應(yīng)用?sync.Once,需要的可以參考一下
    2023-05-05
  • go切片的copy和view的使用方法

    go切片的copy和view的使用方法

    這篇文章主要介紹了go切片的copy和view的使用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • go判斷文件夾是否存在并創(chuàng)建的實(shí)例

    go判斷文件夾是否存在并創(chuàng)建的實(shí)例

    這篇文章主要介紹了go判斷文件夾是否存在,并創(chuàng)建的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • Golang反射修改變量值的操作代碼

    Golang反射修改變量值的操作代碼

    這篇文章主要介紹了Golang反射修改變量值,也就是Golang反射三大定律中的前兩個(gè),即從interface{}到反射對(duì)象和從反射對(duì)象到interface{},需要的朋友可以參考下
    2022-12-12
  • 利用golang的字符串解決leetcode翻轉(zhuǎn)字符串里的單詞

    利用golang的字符串解決leetcode翻轉(zhuǎn)字符串里的單詞

    這篇文章主要介紹了利用golang的字符串解決leetcode翻轉(zhuǎn)字符串里的單詞,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12

最新評(píng)論