分享
  1. 首页
  2. 文章

golang snmp开发学习笔记(二)

wbchen2330 · · 6910 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

soniah/gosnmp是一个纯go语言编写的SNMP包,基于alouca/gosnmp开发。目前提供GetRequest、GetNext、GetBulk、Walk和SetRequest功能,支持IPv4和IPv6, 支持SNMPv2c和SNMPv3。
本文介绍soniah/gosnmp的SetRequest和Walk操作。

SetRequest

snoiah/gosnmp的GoSNMP.Set()方法有一个明显的错误:

func (x *GoSNMP) Set(pdus []SnmpPDU) (result *SnmpPacket, err error) {
 if pdus[0].Type != Integer || pdus[0].Type != OctetString {
 return nil, fmt.Errorf("ERR:gosnmp currently only supports SNMP SETs for Integers and OctetStrings")
 }
 // build up SnmpPacket
 packetOut := x.mkSnmpPacket(SetRequest, 0, 0)
 return x.send(pdus, packetOut)
}

if语句的两个条件应该是"与"的关系,亦即若PDU的类型既不是Integer也不是OctetString则报错(soniah/gosnmp目前Set操作只支持Integer和OctetString两种类型),因此||应改为&&

set_request.go

package main
import (
 "fmt"
 "log"
 "time"
 g "github.com/soniah/gosnmp"
)
func main() {
 var pdus []gs.SnmpPDU
 pdu := gs.SnmpPDU {
 Name: "1.3.6.1.2.1.1.5.0",
 Type: gs.OctetString,
 Value: "new_name",
 }
 pdus = append(pdus, pdu)
 g.Default.Target = "172.18.0.2"
 g.Default.Community = "community"
 err := gs.Default.Connect()
 if err != nil {
 fmt.Printf("Connect() err: %v\n", err)
 }
 defer g.Default.Conn.Close()
 result, err := g.Default.Set(pdus)
 if err != nil {
 fmt.Printf("Set() err: %v", err)
 }
 for i, v := range result.Variables {
 fmt.Printf("%d. oid: %s ", i, v.Name)
 switch v.Type {
 case g.OctetString:
 fmt.Printf("string: %s\n", string(v.Value.([]byte)))
 default:
 fmt.Printf("number: %d\n", g.ToBigInt(v.Value))
 }
 }
}

Walk

Walk不是SNMP的原语,是利用GetNext或GetBulk等操作构建的快捷工具,一般用于一次性获取一棵子树的管理对象,也可用于遍历整个MIB树(注意有些设备厂商为了不让第三方获取完整的MIB,会故意将私有MIB设置成不连续,Walk操作将会在不连续处终止。强烈鄙视这些厂商)。

walk.go

package main
import (
 "fmt" 
 g "github.com/soniah/gosnmp"
)
func main() {
 g.Default.Target = "172.18.0.2"
 g.Default.Community = "community"
 err :=g.Default.Connect()
 if err != nil {
 fmt.Printf("Connect() err: %v", err)
 }
 defer g.Default.Conn.Close()
 oid := ".1.3.6.1.2.1.2.2.1.2"
 //定义回调函数,每个GetNext操作完成后用来处理返回的SnmpPDU
 //函数类型:type WalkFunc func(dataUnit SnmpPDU) error
 fn := func(v g.SnmpPDU) error {
 fmt.Printf("oid: %s, value: ", v.Name)
 switch v.Type{
 case g.OctetString:
 fmt.Printf("%s\n", string(v.Value.([]byte)))
 default:
 fmt.Printf("%d\n", g.ToBigInt(v.Value))
 }
 return nil
 }
 err = g.Default.Walk(oid, fn)
 if err != nil {
 fmt.Printf("Walk() err: %v", err)
 }
}

GoSNMP.Wall()方法使用GetNext操作实现,每个oid需要执行一次GetNext(),效率较低,可以使用BulkWall()方法加以改进,BulkWalk()使用GetBulk操作,一次返回多个oid。
源码中Walk和BulkWalk使用相同的函数,只有一个区别:

maxReps := x.MaxRepetitions
if maxReps <= 0 {
 maxReps = defaultMaxRepetitions
}
getFn := func(oid string) (result *SnmpPacket, err error) {
 switch getRequestType {
 case GetBulkRequest:
 return x.GetBulk([]string{oid}, uint8(x.NonRepeaters), uint8(maxReps))
 case GetNextRequest:
 return x.GetNext([]string{oid})
 default:
 return nil, fmt.Errorf("Unsupported request type: %d", getRequestType)
 }
}

BulkWalk()Walk()的使用方法一样,只需把walk.go代码的g.Default.Walk(oid)换成g.Default.BulkWalk(oid),效果一样,只是使用了更为高效的GetBulk操作。

WalkAll

GoSNMP.Walk()方法采用回调函数处理返回的数据,WalkAll()方法提供了常规的处理方式,将每个操作返回的PDU存储在一个数组里,遍历操作结束后返回给调用者处理。
walk_all.go

package main
import (
 "fmt" 
 g "github.com/soniah/gosnmp"
)
func main() {
 g.Default.Target = "172.18.0.2"
 g.Default.Community = "community"
 err :=g.Default.Connect()
 if err != nil {
 fmt.Printf("Connect() err: %v", err)
 }
 defer g.Default.Conn.Close()
 oid := ".1.3.6.1.2.1.2.2.1.2"
 result, err := g.Default.WalkAll(oid)
 if err != nil {
 fmt.Printf("Walk() err: %v", err)
 }
 for _, v := range result {
 fmt.Printf("oid: %s, value: ", v.Name)
 switch v.Type{
 case g.OctetString:
 fmt.Printf("%s\n", string(v.Value.([]byte)))
 default:
 fmt.Printf("%d\n", g.ToBigInt(v.Value))
 }
 }
}

BulkWalkAll()WalkAll()的使用方法一样,只需把walk_all.go代码中的g.Default.WalkAll(oid)换成g.Default.BulkWalkAll(oid),效果一样,只是使用了更为高效的GetBulk操作。


有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:wbchen2330

查看原文:golang snmp开发学习笔记(二)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
6910 次点击 ∙ 1 赞
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏