亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Go語言otns源碼分析

發布時間:2023-05-05 16:41:17 來源:億速云 閱讀:105 作者:iii 欄目:開發技術

這篇“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()方法,還自定義了其他的方法如runstopprepareStream等等,看名字就容易知道是什么用途

    • 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結構,這個文件里面的函數大概都是添加、刪除節點或者修改什么信息之類的,基本是調用了grpcFieldgrpcServer文件里面的函數,但是在調用之前加了鎖。

    • 這個結構實現了visualize/types.go中的Visualizer接口

    • 并且,這個結構中包含了visualize.SimulationController接口的字段,而visualize.SimulationController定義如下:

    type SimulationController interface {
        Command(cmd string) ([]string, error)
    }

    大概就是命令的入口。

    cmd/otns-replay目錄下的文件

    grpc_Service(包含pb)
    • 定義了grpcService結構,并且實現了VisualizeCommand兩個方法

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

    創建一個新模擬,并設置CmdRunnerVisualizer

    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目錄下的文件

    simulationgrpcVisualizercmdRunner通信的橋梁。

    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)函數產生simulationController

    • simulationController應該是一個介于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源碼分析”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    德江县| 芒康县| 海阳市| 乌拉特前旗| 襄垣县| 清水河县| 都江堰市| 晋江市| 华蓥市| 淮阳县| 疏附县| 开原市| 张家港市| 洪湖市| 马关县| 崇文区| 长岭县| 酉阳| 扬州市| 伊春市| 昆山市| 洮南市| 桦川县| 教育| 白朗县| 资中县| 平原县| 包头市| 华亭县| 宁明县| 抚松县| 仁布县| 乐安县| 奇台县| 临颍县| 温宿县| 奉化市| 塔城市| 泰来县| 临朐县| 类乌齐县|