如何在 Scala 中使用 WebSocket 创建多个聊天室



我正在尝试学习如何使用WebSockets和Akka,使用Play for Scala一书中的聊天示例。

在书中,创建了一个

"聊天室",它在聊天控制器中实例化,内容如下:

val room = Akka.system.actorOf(Props[ChatRoom])

我想扩展此示例,并有多个聊天室可用,而不仅仅是一个。用户可以提供一个字符串,该字符串可以是聊天室"名称",这将创建一个新的聊天室。任何尝试加入此聊天室的人都会相互共享广播,但不会与另一个聊天室中的人共享广播。与IRC非常相似。

我的问题如下:

1: 如果尚不存在唯一名称的聊天室,如何创建该聊天室?2:如何检查现有聊天室是否存在并获取对它的引用?

聊天室名称将通过 URL 或查询参数提供,该部分将微不足道。我只是不完全确定如何唯一地识别 Akka 聊天室,然后按名称检索该 Actor。

您可以在 Akka 中命名演员,因此无需:

Akka.system.actorOf(Props[ChatRoom])

您将拥有:

Akka.system.actorOf(Props[ChatRoom],"room1")

然后,根据您使用的 Akka 版本,使用 Akka.system.actorFor("room1")Akka.system.actorSelection("room1") 获取对所需聊天室的引用。

使用 Akka EventBus 特性。您可以使用 eventBus 和 LookupClassification 来实现基于主题的发布-订阅,其中"主题"是房间 ID,订阅者是每个房间的参与者或每个客户端的 Web 套接字参与者。

import akka.event.EventBus
import akka.event.LookupClassification
final case class MsgEnvelope(topic: String, payload: Any)
/**
 * Publishes the payload of the MsgEnvelope when the topic of the
 * MsgEnvelope equals the String specified when subscribing.
 */
class LookupBusImpl extends EventBus with LookupClassification {
  type Event = MsgEnvelope
  type Classifier = String
  type Subscriber = ActorRef
  // is used for extracting the classifier from the incoming events  
  override protected def classify(event: Event): Classifier = event.topic
  // will be invoked for each event for all subscribers which registered themselves
  // for the event’s classifier
  override protected def publish(event: Event, subscriber: Subscriber): Unit = {
    subscriber ! event.payload
  }
  // must define a full order over the subscribers, expressed as expected from
  // `java.lang.Comparable.compare`
  override protected def compareSubscribers(a: Subscriber, b: Subscriber): Int =
    a.compareTo(b)
  // determines the initial size of the index data structure
  // used internally (i.e. the expected number of different classifiers)
  override protected def mapSize: Int = 128
}

然后注册你的演员(实际上,你会统计每个房间有多少用户,并在用户进入房间时订阅,当房间内没有人时取消订阅并杀死演员

val lookupBus = new LookupBusImpl
lookupBus.subscribe(room1Actor, "room1")
lookupBus.subscribe(room2Actor, "room2")

消息将根据房间 ID 进行切换

lookupBus.publish(MsgEnvelope("room1", "hello room1"))
lookupBus.publish(MsgEnvelope("room2", "hello room2"))
lookupBus.publish(MsgEnvelope("room3", "hello dead letter"))

相关内容

  • 没有找到相关文章

最新更新