我有一个websocket端点,它每秒发送一条文本消息给客户端。客户端从不向服务器发送任何消息。
使用下面的JS代码,它可以按预期工作,并且始终每秒注销一次消息:
var ws = new WebSocket("ws://url_of_my_endpoint");
ws.onmessage = (message) => console.log(message.data);
我想使用Akka HTTP在Scala中创建一个类似的使用者。 我基于official docs创建了以下代码。
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
import system.dispatcher
val url = "ws://url_of_my_endpoint"
val outgoing: Source[Message, NotUsed] = Source.empty
val webSocketFlow =
Http().webSocketClientFlow(WebSocketRequest(url))
val printSink: Sink[Message, Future[Done]] =
Sink.foreach[Message] {
case message: TextMessage.Strict =>
println("message received: " + message.text)
case _ => println("some other message")
}
val (upgradeResponse, closed) =
outgoing
.viaMat(webSocketFlow)(Keep.right)
.toMat(printSink)(Keep.both)
.run()
val connected = upgradeResponse.map { upgrade =>
if (upgrade.response.status == StatusCodes.SwitchingProtocols) {
Done
} else {
throw new RuntimeException(s"Connection failed: ${upgrade.response.status}")
}
}
connected.onComplete(_ => println("Connection established."))
closed.foreach(_ => println("Connection closed."))
问题在于连接会在几秒钟后关闭。有时在1秒后,有时在3-4秒后。 JS客户端工作正常,因此我认为问题不在服务器上。
代码中的问题是什么?应该如何更改它,以便告诉我出了什么问题?
答案 0 :(得分:1)
自您查看文档以来,文档可能已更改,因为现在有一个部分可以解决您遇到的问题: https://doc.akka.io/docs/akka-http/current/client-side/websocket-support.html#half-closed-websockets
它说明:
Akka HTTP WebSocket API不支持半关闭的连接,这意味着如果其中一个流完成,则整个连接都将关闭(在交换“关闭握手”或经过3秒钟的超时之后)。例如,如果我们仅尝试使用来自服务器的消息,则可能会导致意外的行为
所以这行
val outgoing: Source[Message, NotUsed] = Source.empty
引起了问题。并可以通过以下行将其修复,该行将永远不会完成(除非您完成链接到Promise
的{{1}})
Source.maybe
我自己遇到了这个问题,发现行为令人困惑。
答案 1 :(得分:0)
一个问题是您没有通过流发送任何消息:
val outgoing: Source[Message, NotUsed] = Source.empty
尝试以下类似的方法,该方法每秒发送一次随机TextMessage
:
import scala.concurrent.duration._
val outgoing: Source[Message, NotUsed] =
Source
.fromIterator(() => Iterator.continually(TextMessage(scala.util.Random.nextInt().toString)))
.throttle(1, 1 second)