我可以将单个Play WebSocket用于广播和私人消息吗?

时间:2013-09-11 21:43:30

标签: scala websocket playframework-2.1

我需要向我正在处理Play WebSocket消息的客户端发送私有响应,而对于其他消息,我需要向所有客户端广播响应。

在Play聊天示例中,收到的消息为are immediately offloaded to a single Actor

case Connected(enumerator) => 
  // Create an Iteratee to consume the feed, assuming all requests have
  // a JSON "text" node, and delegate all to the Akka Actor:
  val iteratee = Iteratee.foreach[JsValue] { event =>
    default ! Talk(username, (event \ "text").as[String])
  }.map { _ =>
    default ! Quit(username)
  }
  (iteratee,enumerator)

上面,一旦连接被批准,enumerator将被传回,这是指已由同一个Actor创建的单个chatEnumerator

val (chatEnumerator, chatChannel) = Concurrent.broadcast[JsValue]

我认为这不允许我向单个客户端发送消息?我应该删除广播功能并为每个客户创建和跟踪枚举器,然后自己迭代?或者我可以在foreach

中以某种方式获取对特定于客户的枚举器的引用

(我理解内置的灵活性depends on the implementation,但这个用例对我来说似乎很常见。就像使用Socket.IO的WebSockets一样,我可以轻松地向所有客户端发送消息to either ,除了当前请求的发送者之外的所有客户端,或者只是一个客户端。这也是我在Play 2.1.x中尝试实现的目标。)

2 个答案:

答案 0 :(得分:2)

一种方法是使用Enumerator.interleave交错两个枚举器。

因此,您可以使用(Enumerator, Channel)两次创建两对Concurrent.broadcast,一个用于广播另一对用于私有连接,并交错。 (或者可以将Concurrent.unicast用于私人调查员,但我无法弄清楚如何使用它。)

这是一些适用于游戏2.3.0的示例游戏代码。

object Application extends Controller {
  val (publicOut,publicChannel) = Concurrent.broadcast[String]
  def chat = WebSocket.using[String]{ request =>
    val (privateOut,privateChannel) = Concurrent.broadcast[String]
    val in = Iteratee.foreach{
      msg:String => if(msg.startsWith("@")){
        publicChannel.push("Broadcasted: " + msg)
      }else{
        privateChannel.push("Private: " + msg)
      }
    }
    val out = Enumerator.interleave(publicOut,privateOut)
    (in, out)
  }
}

向特定客户端发送消息将是一个有点复杂的代码,但概念是相同的。创建一个Actor,每个websocket保存一对(Enumerator, Channel)并向该actor发送消息。

答案 1 :(得分:1)

这似乎是scala的黑客攻击。 websocket-chat app的java版本使用地图来存储每个用户名和频道。然后循环通过它们。更改/阻止消息只是根据循环内的用户名进行分支。我也在寻找一个好的解决方案。

Map<String, WebSocket.Out<JsonNode>> members = new HashMap<String, WebSocket.Out<JsonNode>>();

这里的完整代码: https://github.com/playframework/playframework/blob/master/samples/java/websocket-chat/app/models/ChatRoom.java