我正在尝试将akka-stream
Source
与websocket连接。
object TestWebServer {
val source1 = Source.actorRef[WsMessage](10, OverflowStrategy.dropHead)
.map { case msg@WsMessage(a,b,c,d,e,f) => println("Received from stream" + msg);TextMessage(c) }
import scala.concurrent.duration._
val source2 = Source.tick(initialDelay = 0 second, interval = 1 second, tick = TextMessage("tick"))
def main(args: Array[String]) {
implicit val system = ActorSystem("my-system")
implicit val materializer = ActorMaterializer()
// needed for the future flatMap/onComplete in the end
implicit val executionContext = system.dispatcher
val requestHandler: HttpRequest => HttpResponse = {
case req@HttpRequest(HttpMethods.GET, Uri.Path("/ws"), _, _, _) =>
req.header[UpgradeToWebSocket] match {
case Some(upgrade) => upgrade.handleMessagesWithSinkSource(Sink.ignore, source1)
case None => HttpResponse(400, entity = "Not a valid websocket request!")
}
case _: HttpRequest => HttpResponse(404, entity = "Unknown resource!")
}
val bindingFuture = Http().bindAndHandleSync(requestHandler, "localhost", 8080)
println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
StdIn.readLine() // let it run until user presses return
bindingFuture
.flatMap(_.unbind()) // trigger unbinding from the port
.onComplete(_ => system.terminate()) // and shutdown when done
}
}
使用Simple Web Socket Client
(SWSC)等客户端,我可以看到
source1
连接,
upgrade.handleMessagesWithSinkSource(Sink.ignore, source1)
我没有看到任何回复SWSC source2
连接,
upgrade.handleMessagesWithSinkSource(Sink.ignore, source2)
我可以看到每隔1秒(预期)在SVSC控制台中显示消息tick
当我向source1
发送消息时,我可以看到消息Received from stream
。所以我相信source1
设置正确。
有谁知道如何让source1
表现得像source2
?将source1
连接到?
谢谢
已更新:
main
之外声明了2个源,以便我可以从另一个Actor系统中使用它来发送消息。
这是分享引用以向source1
发送邮件的正确方法,还是应该使用actorSelection
或变种?source1.mapMaterializedValue { ref => ref ! WsMessage(..., "x", ...); ref ! WsMessage(..., "y", ...) }
但我仍然看不到SWSC中的更新以下是我的测试客户端的代码:
object Test {
def main(args: Array[String]): Unit = {
implicit val system = ActorSystem("my-system2")
implicit val materializer = ActorMaterializer()
// needed for the future flatMap/onComplete in the end
implicit val executionContext = system.dispatcher
val source1Client = TestWebServer.source1
source1Client.mapMaterializedValue { ref => ref ! WsMessage(DateTime.now(), "x", "xx", 0, 0, 0); ref ! WsMessage(DateTime.now(), "y", "yy", 0, 0, 0) }
val source11Client = TestWebServer.source1
val actorRefClient = source11.to(Sink.ignore).run()
actorRef2 ! WsMessage(DateTime.now(), "x", "xx", 0, 0, 0)
}
}
source1
的Test
未到达Source.actorRef
(source1
中的TestWebServer
)actorRefClient
在source1
打印输出TestWebServer
Received from streamWsMessage(...)
答案 0 :(得分:1)
对不起,但是你的更新没有多大帮助。这是一个运行良好的示例程序,当我使用akka-http websockets客户端时以及使用wsta之类的外部工具时:
@foreach ($images as $image )
@if($count==0 OR is_int($count/3))
<?php echo '<div class="row">';?>
@endif
<div class="col-md-3">
<div class="well" style="background:white;">
<img src="{{ url('images/'.$image->filepath) }}" alt="" class="" height="100" width="100" ></br>
{{ $image->title }}<br>
{{$image->filepath }}
</div>
</div>
@if($count==0 OR is_int($count/3))
<?php echo '</div>' ;?>
@endif
<?php $count++;?>
@endforeach
我认为此程序与您的程序没有任何重要区别。该程序还包括服务器和客户端,因此您可以启动服务器,然后多次启动客户端。例如,以下是两个客户端运行后的服务器输出:
import java.time.Instant
import scala.io.StdIn
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.http.scaladsl.model.ws.{TextMessage, UpgradeToWebSocket, WebSocketRequest}
import akka.stream.{ActorMaterializer, OverflowStrategy}
import akka.stream.scaladsl.{Flow, Sink, Source}
case class WsMessage(a: Instant, b: String, c: String, d: Int, e: Int, f: Int)
object MainServer extends App {
implicit val actorSystem = ActorSystem()
implicit val materializer = ActorMaterializer()
implicit val executionContext = actorSystem.dispatcher
val source = Source.actorRef[WsMessage](10, OverflowStrategy.dropHead)
.map {
case msg@WsMessage(_, _, c, _, _, _) =>
println(s"Received from stream: $msg")
TextMessage(c)
}
.mapMaterializedValue { ref =>
ref ! WsMessage(Instant.now(), "a", "x", 0, 0, 0)
ref ! WsMessage(Instant.now(), "b", "y", 0, 0, 0)
}
val requestHandler: HttpRequest => HttpResponse = {
case req@HttpRequest(HttpMethods.GET, Uri.Path("/ws"), _, _, _) =>
req.header[UpgradeToWebSocket] match {
case Some(upgrade) => upgrade.handleMessagesWithSinkSource(Sink.ignore, source)
case None => HttpResponse(StatusCodes.BadRequest, entity = "Not a valid websocket request!")
}
case _ =>
HttpResponse(StatusCodes.NotFound, entity = "Unknown resource!")
}
val bindingFuture = Http().bindAndHandleSync(requestHandler, "localhost", 8080)
println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
StdIn.readLine()
bindingFuture
.flatMap(_.unbind())
.onComplete(_ => actorSystem.terminate())
}
object MainClient extends App {
implicit val actorSystem = ActorSystem()
implicit val materializer = ActorMaterializer()
implicit val executionContext = actorSystem.dispatcher
Http()
.singleWebSocketRequest(WebSocketRequest(Uri("ws://localhost:8080/ws")), Flow.fromSinkAndSource(Sink.foreach(println), Source.empty))
Thread.sleep(5000)
actorSystem.terminate()
}
这是客户输出之一:
Server online at http://localhost:8080/
Press RETURN to stop...
Received from stream: WsMessage(2016-06-28T08:58:21.478Z,a,x,0,0,0)
Received from stream: WsMessage(2016-06-28T08:58:21.478Z,b,y,0,0,0)
Received from stream: WsMessage(2016-06-28T08:58:29.925Z,a,x,0,0,0)
Received from stream: WsMessage(2016-06-28T08:58:29.925Z,b,y,0,0,0)
当我运行TextMessage.Strict(x)
TextMessage.Strict(y)
时,我看到类似的事情。
此外,您在wsta ws://localhost:8080/ws
,Source
或Sink
s声明的位置无关紧要:它们是不可变的蓝图,只有在{{1}时才能“行动” }}