【问题标题】:Port scanning in Scala: Application hangs for a closed port on the remote hostScala中的端口扫描:应用程序挂起远程主机上的关闭端口
【发布时间】:2014-10-11 17:18:54
【问题描述】:

我一直在尝试创建一个应用程序,该应用程序需要尽快扫描网络(主要是 LAN)上的开放端口。

我四处搜索,发现一个很棒的方法使用以下代码:

(1 to 65536).par.map { case port ⇒
  try {
    val socket = new java.net.Socket("127.0.0.1", port)
    socket.close()
    println(port)
    port
  } catch {
    case _: Throwable ⇒ -1
  }
}.toSet

但是,代码的问题是,如果我输入 127.0.0.1 或 localhost 以外的任何位置(例如 192.168.1.2),应用程序就会冻结。

知道为什么会发生这种情况以及如何解决吗?

附:我还尝试使用 socket.setSoTimeout(1500) 设置套接字超时,但没有任何变化。

【问题讨论】:

  • 当您建立连接时,您会阻止等待,直到远程主机响应或连接尝试超时。在您的情况下,尝试连接到不存在的主机意味着您将花费所有时间等待超时。与 any 程序一样,如果您不忽略异常,您就会意识到这一点。
  • @kdgregory 我尝试设置 socket.setSoTimeout(3000) 但也没有用。
  • 3 秒乘以 65536 仍然是很多时间。
  • 您和支持您的人需要阅读一些文档。 “并行”并不意味着“无限线程”。
  • 人们通过提问来学习。没有错。

标签: java scala port


【解决方案1】:

有点像

import scala.concurrent.{Future, Await}
import scala.concurrent.duration._
import scala.util.Try
import scala.concurrent._
import java.util.concurrent.Executors

implicit val ec = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(100)) 

def openPorts(address:String ="127.0.0.1",duration:Duration = 10 seconds, fromPort:Int = 1, toPort:Int = 65536) = {
 val socketTimeout = 200
 val result = Future.traverse(fromPort to toPort ) { port =>
  Future{ Try {
    val socket = new java.net.Socket()
    socket.connect(new java.net.InetSocketAddress(address, port),socketTimeout)
    socket.close()
    port
  } toOption } 
 } 
 Try {Await.result(result, duration)}.toOption.getOrElse(Nil).flatten
}


scala> val localPorts openPorts(fromPort = 10, toPort = 1000)
localPorts: scala.collection.immutable.IndexedSeq[Int] = Vector(22, 631)
scala> val remotePorts = openPorts(fromPort = 10, toPort = 1000, address="192.168.1.20")
remotePorts: scala.collection.immutable.Seq[Int] = List() //we ate the timeout

scala> val remotePorts = openPorts(fromPort = 12000, toPort = 13000, address="91.190.218.61", duration=30 seconds)
remotePorts: scala.collection.immutable.Seq[Int] = Vector(12345, 12350)

【讨论】:

  • 感谢您的回答。我一直在检查 Futures API,它似乎很有帮助。
【解决方案2】:

虽然 Ashalynd 的回答也很有效,但当我再次使用这个应用程序时,我找到了一个使用 Futures 的解决方案,也许更简单。

这里是代码

  import scala.concurrent._
  import ExecutionContext.Implicits.global

  object TestOne extends App{

    println("Program is now running")

    val dataset: Future[Set[Int]] = future {
      (1 to 6335).map {
        case port =>
          try {
            val socket = new java.net.Socket("127.0.0.1", port)
            socket.close()
            println("The port is open at " + port)
            port
          } catch {
            case _: Throwable => -1
          }
      }.toSet
    }
  }

【讨论】:

  • 与我的解决方案的不同之处在于您仍然按顺序浏览端口列表,而 Future.traverse 可以并行执行(当然,如果相应地配置了执行上下文)。
  • 是的,你是对的。感谢你的回答。当我问这个问题时,我是 Scala 的新手,并且更了解 JS 等脚本语言的并发模型。我玩 Scala Futures 已经有一段时间了,现在我明白为什么你的解决方案更好了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-03
  • 2018-06-07
  • 1970-01-01
相关资源
最近更新 更多