[英]Akka Stream, Tcp().bind, handle when the client close the socket
I'm quite new in Akka Stream and I'd like to learn how handle a TCP socket for a project of mine.我是 Akka Stream 的新手,我想了解如何为我的项目处理 TCP 插座。 I took this piece of code from the Akka Stream official documentation .
我从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)
}
If I connect from the terminal using netcat I can see that the Akka Stream TCP socket works as expected.如果我使用 netcat 从终端连接,我可以看到 Akka Stream TCP 套接字按预期工作。 I also found out that If I need to close the connection using an user message, I can use a
takeWhile
as follow我还发现如果我需要使用用户消息关闭连接,我可以使用
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)
}
What I can't find is how to manage a socket closed by a CMD + C
action.我找不到的是如何管理由
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. 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. 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. Is there a way to manage that?
有没有办法管理它?
connection.handleWith(echo)
is syntactic sugar for connection.flow.joinMat(echo)(Keep.right).run()
which will have the materialized value of echo
, which is generally not useful. connection.handleWith(echo)
是connection.flow.joinMat(echo)(Keep.right).run()
的语法糖,它将具有echo
的具体化值,这通常没有用。 Flow.via.map.takeWhile
has NotUsed
as a materialized value, so that's also basically useless. Flow.via.map.takeWhile
有NotUsed
作为物化值,所以这也基本上没用。 However, you can attach stages to echo
which will materialize differently.但是,您可以将阶段附加到以不同方式实现的
echo
。
One of these is .watchTermination
:其中之一是
.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)
}
}
This will not distinguish between your side or the remote side closing the connection normally;这将无法区分您端或远程端是否正常关闭连接; it will distinguish the stream failing.
它将区分 stream 失败。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.