我需要向当前正在处理Play WebSocket消息的客户端发送一个私有响应,而对于其他消息,我需要向所有客户端广播响应。
在Play聊天示例中,传入消息立即被卸载到单个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
回传,这指的chatEnumerator
是由同一Actor已经创建的单个:
val (chatEnumerator, chatChannel) = Concurrent.broadcast[JsValue]
我认为这不允许我仅向单个客户端发送消息吗?我应该删除广播功能并为每个客户端创建并跟踪枚举数,然后自己进行迭代吗?还是可以通过某种方式获得对特定于客户的枚举数的引用foreach
?
(我的理解是内在的灵活性依赖于实现,但这种使用情况似乎相当普遍给我。使用使用WebSockets时就像Socket.IO,我可以很容易地发送消息要么所有客户,所有客户端除了当前的发送者请求或一个客户端。这也是我在Play 2.1.x中要实现的目标。)
一种方法是使用交错两个枚举器Enumerator.interleave
。
因此,您可以创建两次(Enumerator, Channel)
使用Concurrent.broadcast
两次,一对用于广播,另一对用于私人连接,并进行交织。(或者可能仅Concurrent.unicast
用于私有枚举器,但我不知道如何使用它。)
这是一些在play 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
容纳(Enumerator, Channel)
每个websocket的对,然后将消息发送给actor。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句