scala - 允许与 Akka 流作为 tcp 服务器的单一连接

标签 scala tcp server akka akka-stream

我正在尝试使用 Akka 流构建一个简单的 tcp 服务器。

 Tcp()
  .bind(props.host, props.port)
  .to(Sink.foreach(_.handleWith(handler)))
  .run()
  .onComplete {
    case Success(i) => logger.info(s"Server is bound at ${props.host}:${props.port}")
    case Failure(e) => logger.error("Server binding failure", e)
  }

我想一次允许最多一个连接。为此,我将以下行添加到我的 application.conf 文件中。

akka.io.tcp.max-channels = 2

通过这种配置,akka 一次只允许一个连接。但是,一旦尝试第二次连接,它就会拒绝请求并失败并显示以下消息:

Could not register incoming connection since selector capacity limit is reached, closing connection

从这一点来看,不可能建立任何连接,因为 Tcp 服务器已关闭。

问题:一次只启用一个连接的正确方法是什么?主要目的是回答第一个连接请求并拒绝其他仍在进行中的连接请求。在关闭前一个连接后,应该可以再次建立另一个连接。正如我所提到的,任何时候都应该只允许一个连接。

奖励:是否可以提供白名单以使 akka 流仅接受来自此列表的连接? 我打算只允许已知的 IP 地址连接我的服务器。要做到这一点,我认为知道拒绝请求的正确方法就足够了。所以我可以将传入连接的 IP 地址与给定列表进行比较,如果不存在则拒绝。但也欢迎任何更好的解决方案。

最佳答案

Tcp 的 Bind 方法有一个参数 options,它接受一个 Traversable of Socket 选项。您可以像这样将 smth 传递给该参数:

case class AllowedAddresses(addresses: Seq[InetAddress]) extends SocketOption {
    override def beforeConnect(s: Socket): Unit = {
      if (!addresses.contains(s.getInetAddress)) s.close()
    }
  }

因此您的代码将如下所示:

Tcp()
  .bind(props.host, props.port, options = List(AllowedAddresses(listOfAddresses)))
  .to(Sink.foreach(_.handleWith(handler)))
  .run()
  .onComplete {
    case Success(i) => logger.info(s"Server is bound at ${props.host}:${props.port}")
    case Failure(e) => logger.error("Server binding failure", e)
  }

限制请求数的方法是一样的,查看SocketOptions trait中的方法

附言。没试过运行,查过stream API才得出结论,请检查正确性。

关于scala - 允许与 Akka 流作为 tcp 服务器的单一连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41332284/

相关文章:

scala - 使用带有 bintray-sbt 插件的 sbt 时如何发布快照?

Scala 导入不起作用 - 对象 <name> 不是包的成员,sbt 在导入中预先添加当前包 namespace

Microsoft IIS httpd 10.0 基于 Azure PCI 合规性 CPE 的漏洞

tcp - TCP中的两个半双工连接

java - 可序列化对象的 transient 属性被反序列化为 null

scala - 具有多个参数列表的 Scala 方法中的尾递归

java - 对象 kafka 不是包 org.apache 的成员

c - 检测断开连接的客户端而不阻塞 (C)

Swift 使用 CloudKit 保存新评论

python - 如何开始在 Linux 主机上使用 python