[英]Akka Stream, Tcp().bind, handle when the client close the socket
我是 Akka Stream 的新手,我想了解如何为我的项目处理 TCP 插座。 我从Akka Stream 官方文档中获取了这段代码。
import akka.stream.scaladsl.Framing
val connections: Source[IncomingConnection, Future[ServerBinding]] =
Tcp().bind(host, port)
connections.runForeach { connection =>
println(s"New connection from: ${connection.remoteAddress}")
val echo = Flow[ByteString]
.via(Framing.delimiter(ByteString("\n"), maximumFrameLength = 256, allowTruncation = true))
.map(_.utf8String)
.map(_ + "!!!\n")
.map(ByteString(_))
connection.handleWith(echo)
}
如果我使用 netcat 从终端连接,我可以看到 Akka Stream TCP 套接字按预期工作。 我还发现如果我需要使用用户消息关闭连接,我可以使用takeWhile
如下
import akka.stream.scaladsl.Framing
val connections: Source[IncomingConnection, Future[ServerBinding]] =
Tcp().bind(host, port)
connections.runForeach { connection =>
println(s"New connection from: ${connection.remoteAddress}")
val echo = Flow[ByteString]
.via(Framing.delimiter(ByteString("\n"), maximumFrameLength = 256, allowTruncation = true))
.map(_.utf8String)
.takeWhile(_.toLowerCase.trim != "exit") // < - - - - - - HERE
.map(_ + "!!!\n")
.map(ByteString(_))
connection.handleWith(echo)
}
我找不到的是如何管理由CMD + C
操作关闭的套接字。 Akka Stream use Akka.io to manage the TCP connection internally, so it must send some of its PeerClose
messages when the socket is closed. So, my understanding of Akka.io tells me that I should receive a feedback from the socket closing but I can't find how to do that with Akka Stream. 有没有办法管理它?
connection.handleWith(echo)
是connection.flow.joinMat(echo)(Keep.right).run()
的语法糖,它将具有echo
的具体化值,这通常没有用。 Flow.via.map.takeWhile
有NotUsed
作为物化值,所以这也基本上没用。 但是,您可以将阶段附加到以不同方式实现的echo
。
其中之一是.watchTermination
:
connections.runForeach { connection =>
println(s"New connection from: ${connection.remoteAddress}")
val echo: Flow[ByteString, ByteString, Future[Done]] = Flow[ByteString]
.via(Framing.delimiter(ByteString("\n"), maximumFrameLength = 256, allowTruncation = true))
.map(_.utf8String)
.takeWhile(_.toLowerCase.trim != "exit") // < - - - - - - HERE
.map(_ + "!!!\n")
.map(ByteString(_))
// change the materialized value to a Future[Done]
.watchTermination()(Keep.right)
// you may need to have an implicit ExecutionContext in scope, e.g. system.dispatcher,
// if you don't already
connection.handleWith(echo).onComplete {
case Success(_) => println("stream completed successfully")
case Failure(e) => println(e.getMessage)
}
}
这将无法区分您端或远程端是否正常关闭连接; 它将区分 stream 失败。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.