在Play Framework WebSockets中广播消息 [英] Broadcasting messages in Play Framework WebSockets

查看:114
本文介绍了在Play Framework WebSockets中广播消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Concurrent.unicast[JsValue]在Play Framework WebSockets中推送消息,并且我想优化向多个用户发送同一条消息的过程.可以使用多个Concurrent.Channel广播消息吗?

I'm pushing messages in Play Framework WebSockets using Concurrent.unicast[JsValue], and I want to optimize sending the same message to multiple users. Is it possible to broadcast message using somehow multiple Concurrent.Channel?

推荐答案

简短答案

为每个用户维护单独的频道,并具有与用户相关联的组

Maintain separate channel for each user and have groups associated with users

好答案

package controllers

import akka.actor.Actor
import play.api.libs.iteratee.Enumerator
import play.api.libs.iteratee.Concurrent.Channel
import play.api.libs.iteratee.Concurrent
import play.api.Logger
import play.api.libs.iteratee.Iteratee
import play.api.libs.concurrent.Execution.Implicits.defaultContext

object AdvancedRoomMessages {
  case class Join(name: String)
  case class BroadcastGroup(msg: String, gName: String)
  case class BroadcastAll(msg: String)
  case class AddGroup(gName: String)
  case class RemoveGroup(gName: String)
  case class AddUserToGroup(userName: String, gName: String)
  case class removeUserFromGroup(userName: String, gName: String)
}


class AdvancedRoom extends Actor {
  import scala.collection.mutable._


  /**
   * common channel for communication
   */


  val (enumerator, channel) = Concurrent.broadcast[String]



  /**
   * every user has his own channel
   */
  val users = Map[String, (Enumerator[String],Channel[String])]()

  /**
   * users can be grouped
   */
  val groups = Map[String, Option[Set[String]]]()

  import AdvancedRoomMessages._

  def receive = {
    case Join(name) => {
      /**
       * join request from the user
       */
      if(users contains name) {
        /**
         * existing user
         */
        val iteratee = Iteratee.ignore[String]
        sender ! ((iteratee, users(name)._1))
      }else {
        /**
         * join request from a new user
         */

        /**
         * create new broadcast channel
         */
        val (enumerator, channel) = Concurrent.broadcast[String]
        users += ((name, (enumerator, channel)))
        val iteratee = Iteratee.foreach[String](msg => {
          //do something with the message
        }).map{ _ => {
          /**
           * user closed his websocket client, so remove the user
           * warning ... also remove the corresponding user name in groups
           */
          users(name)._2.eofAndEnd()
          users -= name
        }}
        sender ! (iteratee, enumerator)
      }
    }
    case BroadcastGroup(msg, gName) => {
      groups(gName) match {
        case Some(gMates) => {
          gMates.foreach { person => users(person)._2.push(msg)}
        }
        case None => Logger.info("empty group") //ignore sending message
      }
    }
    case BroadcastAll(msg) => {
      channel push msg
    }
    case AddGroup(gName: String) => {
      groups += ((gName, None))
    }
    case RemoveGroup(gName: String) => {
      groups -= gName
    }
    case AddUserToGroup(userName, gName) => {
      groups(gName) match {
        case Some(gMates) => gMates += userName
        case None => Set(userName)
      }
    }
  }
}

这篇关于在Play Framework WebSockets中广播消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆