PlayFramework 2.3.x如何使用websockets向所有人和特定客户端广播

时间:2014-12-14 12:20:46

标签: scala playframework websocket

更新 这是在这里回答@ https://groups.google.com/forum/#!topic/play-framework/P-tG6b_SEyg -

这里的第一个Play / Scala应用程序,我有点挣扎。我想要实现的是特定渠道(websocket url)上的用户之间的协作。我试图按照书中的示例" Play Framework Essentials"并试图适应我的用例。根据客户端的请求,我要将信息广播给在此频道上通话的所有客户端,或者只将信息发送回发送初始请求的客户端。广播部分正在工作,但我无法弄清楚如何将信息本身发送回请求的客户端。

在我的控制器中我有

def ws(channelId: String) = WebSocket.tryAccept[JsValue] { implicit request =>
  getEnumerator(channelId).map { out =>
    val in = Iteratee.foreach[JsValue] { jsMsg =>
      val id = (jsMsg \ "id").as[String]
      // This works and broadcasts that the user has connected
      connect(id, request.session.get("email").get)
      // Not sure how to return the result of this just to the client of the request
      retrieve(id)
    }
    Right((in, out))
  }
}

private def getEnumerator(id: String): Future[Enumerator[JsValue]] = {
  (myActor ? GetEnumerator(id)).mapTo[Enumerator[JsValue]]
}

private def connect(id: String, email: String): Unit = {
  (myActor ! Connect(id, email))
}

// I have a feeling this is an incorrect return type and I need to return a Future[JsValue]    
//and somehow feed that to the enumerator
private def retrieve(id: String): Future[Enumerator[JsValue]] = {
  (myActor ? RetrieveInfo(id)).mapTo[Enumerator[JsValue]]
}

在我的演员

class MyActor extends Actor {
  var communicationChannels = Map.empty[String, CommunicationChannel]

  override def receive: Receive = {
    case GetEnumerator(id) => sender() ! getOrCreateCommunicationChannel(id).enumerator
    case Connect(id, email) => getOrCreateCommunicationChannel(id).connect(email)
    case RetrieveInfo(id) => sender() ! Json.toJson(Info(id, "details for " + id))
  }


  private def getOrCreateCommunicationChannel(id: String): CommunicationChannel = {
    communicationChannels.getOrElse(id, {
      val communicationChannel = new CommunicationChannel
      communicationChannels += id -> communicationChannel
      communicationChannel
    })
  }
}

object MyActor {

  def props: Props = Props[MyActor]

  class CommunicationChannel {
    val (enumerator, channel) = Concurrent.broadcast[JsValue]

    def connect(email: String) = {
      channel.push(Json.toJson(Connected(email)))
    }
  }
}

Connect,Connected,Info等只是定义了读取和写入的案例类

有人可以告诉我是否可以使用这种方法将消息推送给特定用户而不是将其广播给每个人?或者如果我需要以另一种方式实现这个

还有一种方法可以向除了你自己以外的所有人播放

非常感谢任何帮助

谢谢!

0 个答案:

没有答案