【问题标题】:How to get Asynchronous SNMPv2 in SCALA with snmp4j如何使用 snmp4j 在 SCALA 中获取异步 SNMPv2
【发布时间】:2015-03-18 14:59:05
【问题描述】:

我正在查询 SNMP,我想在数据检索完成时执行回调。为此,我使用以下代码:

 def treeWalk(rootOid: String)(callback: (Seq[Tuple2[OID, Variable]]) => Unit) {//{{{
    val transport = new DefaultUdpTransportMapping
    val snmp = new Snmp(transport)
    transport.listen

    val target = new CommunityTarget
    target.setCommunity(new OctetString(community))
    target.setAddress(GenericAddress.parse("udp:" + address + "/161"))
    target.setRetries(retries)
    target.setTimeout(timeout)
    target.setVersion(SnmpConstants.version2c)

    val treeUtil = new TreeUtils(snmp, new DefaultPDUFactory)
    var variables: Seq[VariableBinding] = List()
    var _isFinished = false

    val listener = new TreeListener {
        def next(event: TreeEvent) = {
            println("NEXT")
            val vars = event.getVariableBindings
            if(vars != null)
               variables ++= vars
            true
        }
        def isFinished() = _isFinished
        def finished(event: TreeEvent) {
            val vars = event.getVariableBindings
            println("DONE")
            if(vars != null)
              variables ++= vars
            _isFinished = true
            snmp.close
            callback(variables.map(v => (v.getOid, v.getVariable)))
        }
  }
  treeUtil.walk(target, Array(new OID(rootOid)), null, listener)
}

我没有收到任何错误或异常,但是我从未在 next() 和 finished() 中看到打印行,而且回调也没有执行。我做错了什么,我应该如何将事件侦听器挂钩?

PS:单行同步版本返回数据就好了……

我正在使用 Scala 2.11.6 和 SNMP4J 2.3

【问题讨论】:

  • 我对 SNMP 不熟悉,但如果它和我见过的大多数回调一样,那么您在哪里等着让调用时间完成以便可以执行回调?
  • 我正在调用您在此处看到的方法,其中“println”作为回调函数。据我了解,回调应该是方法之后调用堆栈中的下一个条目。所以这意味着不涉及等待,该方法将在完成时调用它。对吗?
  • 在阻塞的情况下,是的。但是,当您有一个带有回调的异步调用时,程序可以在异步操作完成之前终止。您可以通过使其休眠或以stackoverflow.com/questions/16256279/wait-for-several-futures 中显示的方式重组程序来完成此操作,以便等待方法返回。
  • 基本上,主线程启动异步过程,然后用完指令,所以它终止,这会导致你程序的所有线程终止,包括任何正在运行的线程正在处理异步调用。
  • 确实你是对的,最快的解决方案是 Thread.sleep 。我将在未来进一步实施它。

标签: scala asynchronous functional-programming snmp4j


【解决方案1】:

在处理回调时,您必须考虑到主线程可以在异步调用之前轻松完成,从而导致主线程(以及程序的其余部分)在异步任务完成之前终止,并且回调到达。执行此操作的简单方法是调用Thread.sleep() 并使您的主线程暂停特定的时间等待。但是,您可以对此进行改进。一种选择是使用如下代码的 sn-p:

var callbackComplete = false
someAsyncMethodWithCallback(callback)
while (!callbackComplete){
    Thread.sleep(100)
}

那么你需要做的就是让你的回调包含一行callbackComplete = true,这将使它终止。

但是,这远非理想(但如果您只需要快速的临时修复,则很好)。理想情况下,您应该通读 Scala 文档中的 Futures and Promises 页面。它详细说明了如何正确处理 Futures 以及处理失败,并且应该被视为处理异步调用的适当资源。

【讨论】:

  • 谢谢,我正在使用长线程睡眠来测试它,但是我应该转向期货和承诺,因为它对性能来说太重要了,不能有一个平坦的睡眠量。
猜你喜欢
  • 1970-01-01
  • 2018-02-04
  • 1970-01-01
  • 1970-01-01
  • 2016-06-15
  • 1970-01-01
  • 2018-09-08
  • 2021-11-20
相关资源
最近更新 更多