服务器代码:
object EchoService {
def route: Route = path("ws-echo") {
get {
handleWebSocketMessages(flow)
}
} ~ path("send-client") {
get {
sourceQueue.map(q => {
println(s"Offering message from server")
q.offer(BinaryMessage(ByteString("ta ta")))
} )
complete("Sent from server successfully")
}
}
val (source, sourceQueue) = {
val p = Promise[SourceQueue[Message]]
val s = Source.queue[Message](100, OverflowStrategy.backpressure).mapMaterializedValue(m => {
p.trySuccess(m)
m
})
(s, p.future)
}
val flow =
Flow.fromSinkAndSourceMat(Sink.ignore, source)(Keep.right)
}
客户代码:
object Client extends App {
implicit val actorSystem = ActorSystem("akka-system")
implicit val flowMaterializer = ActorMaterializer()
val config = actorSystem.settings.config
val interface = config.getString("app.interface")
val port = config.getInt("app.port")
// print each incoming strict text message
val printSink: Sink[Message, Future[Done]] =
Sink.foreach {
case message: TextMessage.Strict =>
println(message.text)
case _ => println(s"received unknown message format")
}
val (source, sourceQueue) = {
val p = Promise[SourceQueue[Message]]
val s = Source.queue[Message](100, OverflowStrategy.backpressure).mapMaterializedValue(m => {
p.trySuccess(m)
m
})
(s, p.future)
}
val flow =
Flow.fromSinkAndSourceMat(printSink, source)(Keep.right)
val (upgradeResponse, sourceClosed) =
Http().singleWebSocketRequest(WebSocketRequest("ws://localhost:8080/ws-echo"), flow)
val connected = upgradeResponse.map { upgrade =>
// just like a regular http request we can get 404 NotFound,
// with a response body, that will be available from upgrade.response
if (upgrade.response.status == StatusCodes.SwitchingProtocols || upgrade.response.status == StatusCodes.OK ) {
Done
} else {
throw new RuntimeException(s"Connection failed: ${upgrade.response.status}")
}
}
connected.onComplete(println)
}
当我点击http://localhost:8080/send-client
时,我看到消息传到客户端但是一段时间后如果尝试再次发送给客户端,我在客户端看不到任何消息:s。我也试过source.concatMat(Source.maybe)(Keep.right)
但没有运气:(
编辑:我使用js客户端进行了测试,不知何故连接/流量在服务器端关闭,无论如何都要阻止这个?以及如何在使用akka-http websocket客户端时收听此事件:s
答案 0 :(得分:5)
您好,
它不保持连接的原因是因为默认情况下全部 默认情况下,HTTP连接启用idle-timeout以保持系统 如果客户在没有任何信号的情况下消失,则会泄漏连接。
克服这种限制的一种方法(实际上是我推荐的 方法)是在客户端注入保持活动消息 (服务器否则忽略的消息,但通知底层 连接仍然有效的HTTP服务器。
您可以将HTTP服务器配置中的空闲超时覆盖为 更大的价值,但我不建议这样做。
如果您使用的是基于流的客户端,请在何时注入心跳 必要的就像调用
keepAlive
并为其提供时间一样简单 您要注入的消息的间隔和工厂: http://doc.akka.io/api/akka/2.4.7/index.html#akka.stream.scaladsl.Flow@keepAlive U>:输出:FlowOps.this.Repr [U]该组合子将确保没有超过T的句号 沉默,因为如果有必要,它将注入元素以保持合同 (如果有足够的背景流量,则不会注入任何东西)
-Endre
谢谢你Endre :),工作片段..
// on client side
val (source, sourceQueue) = {
val p = Promise[SourceQueue[Message]]
val s = Source.queue[Message](Int.MaxValue, OverflowStrategy.backpressure).mapMaterializedValue(m => {
p.trySuccess(m)
m
}).keepAlive(FiniteDuration(1, TimeUnit.SECONDS), () => TextMessage.Strict("Heart Beat"))
(s, p.future)
}