Source.actorRef未通过akka流流传输到websocket

Source.actorRef未通过akka流流传输到websocket,akka,akka-stream,Akka,Akka Stream,我正在尝试将akka流源与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.concurr

我正在尝试将
akka流
与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
  }
}
使用诸如
简单Web套接字客户端(SWSC)之类的客户端,我可以看到

  • 如果我将websocket连接到
    source1
    upgrade.HandleMessageWithSinkSource(Sink.ignore,source1)
    我看不到SWSC的任何回复
  • 如果我将websocket连接到
    source2
    upgrade.handleMessagesWithSinkSource(Sink.ignore,source2)
    我可以看到SVSC控制台每隔1秒显示一条消息
    tick
    (预期)
当我向
source1
发送消息时,我可以看到从流中收到的消息
。因此我相信
source1
设置正确

有人知道我如何使
source1
表现得像
source2
?要将
source1
连接到什么特殊设备

多谢各位

已更新

  • 我已经更新了代码。实际上,我在
    main
    之外声明了这两个源,以便我可以从另一个Actor系统使用它来发送消息。 这是共享ref以向
    source1
    发送消息的正确方法,还是应该使用类似
    actorSelection
    或变体的方法
  • 正如弗拉基米尔·马特维耶夫(Vladimir Matveev)所提到的,我尝试过:
    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)

  }
}
  • Test
    中的
    source1
    未到达
    Source.actorRef
    TestWebServer中的
    source1
  • actorRefClient
    在控制台的
    TestWebServer
    中的
    source1
    中从streamWsMessage(…)接收到

    • 很抱歉,您的更新没有多大帮助。下面是一个示例程序,在我使用akka http websockets客户端和使用以下外部工具时运行良好:

      我看不出这个计划和你的有什么重要区别。该程序还包括服务器和客户端,因此您可以启动服务器,然后多次启动客户端。例如,以下是两次客户端运行后的服务器输出:

      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)
      
      当我运行
      wstaws://localhost:8080/ws
      时,我看到了类似的情况


      另外,无论您在哪里声明
      s、
      接收器
      s或
      s,它们都是不可变的蓝图,只有在
      run()

      您的代码对我来说正确时,它们才能“行动”。您确定要将消息发送给正确的参与者吗?我在源代码上做了
      mapMaterializedValue{ref=>ref!WsMessage(…,“x”,…);ref!WsMessage(…,“y”,…)}
      ,我可以在websocket连接的输出中看到
      x
      y
      。弗拉基米尔,请查看我的更新-谢谢!如果我使用您的代码,我现在可以看到打印出来的消息。我所看到的代码与您的代码之间的唯一区别是,您的源代码从其定义中发送消息。在我的代码中,我检索了
      源代码
      ,并向其发送了一条消息(我基本上希望外部参与者向
      源代码
      发送一条消息)。我认为问题可能来自于在一个JVM中运行Web服务器,而我在另一个JVM(不同的程序)中启动我的测试客户机。是吗?@ccheneson,你的测试客户是什么?在我上面的示例中,有一个
      MainClient
      对象,它是一个单独的应用程序。当然,当我与
      MainServer
      一起测试它时,它们是在单独的JVM中启动的。@ccheneson,还有,您到底是如何“检索”源参与者的?如果没有
      mapMaterializedValue
      并将其存储在
      var
      或类似的东西中,我看不出有什么办法可以做到这一点,这当然不是很好。对不起,措辞不好。所谓测试客户端,我指的是我的程序,它向
      源代码
      发送WsMessage。我基本上是这样的:从外部参与者那里,我想发送一些
      WsMessage
      消息到
      source
      ,通过WebSocketTorry糟糕的措辞将这些消息流回到客户端。所谓测试客户端,我指的是我的程序,它向
      源代码
      发送WsMessage。我基本上是这样想的:从外部参与者,我想发送一些
      WsMessage
      消息到
      source
      ,通过WebSocket将这些消息流回到客户端(例如web浏览器),这就是为什么我将
      source
      声明移到
      main
      之外,以便我可以从另一个地方导入它。我觉得这也不好。如果您对如何从外部访问
      source
      akka remote
      ?)有其他想法,请告诉我-谢谢
      TextMessage.Strict(x)
      TextMessage.Strict(y)