使用akka和scala实现一个简单的聊天服务器

时间:2016-06-30 06:33:56

标签: scala akka

我正在学习Akka和Scala并试图用它构建一个简单的聊天服务器。我编写了以下代码来创建一个简单的会话管理器来管理新创建的Actors。我能够创建新的actor并将ActorRef放到HashMap中,但是当我尝试向特定的Actor发送消息时,该消息就不会被Actor接收。

这是代码。

import akka.actor.{ ActorRef, ActorSystem, Props, Actor, Inbox }
import scala.concurrent.duration._
import scala.collection.mutable.HashMap


case class ChatMsg(from:String,message:String)
case class Login(username:String)

class Session(userID:String) extends Actor{
    val loginTime = System.currentTimeMillis
    println(s"Session created time :$loginTime")
    def receive ={
    case ChatMsg(from,message) => println(s"message :$message from    $from !")
    }
}

class SessionManager extends Actor{
val system = ActorSystem("ChatSession")
val sessions = new HashMap[String,ActorRef]
val inbox = Inbox.create(system)

def receive ={
    case Login(username) =>
        println(s"$username Login, now create Actor")
        val session = system.actorOf(Props(new Session(username)))
        sessions += (username->session)
        println(s"session added $sessions")
    case ChatMsg(from,message) => 
        sessions(from) ! message 

}
}



object MyAkkaTest extends App {

val system = ActorSystem("MyAkkaTest")
val user = system.actorOf(Props[SessionManager],"MyActor")
val inbox = Inbox.create(system)
user ! Login("Mary")
user ! Login("John")
user ! ChatMsg("Mary","this is a testing message") //this message can never sent...


}

1 个答案:

答案 0 :(得分:2)

问题是你的Session actor期望获得ChatMsg类型的消息,但是你发送的是一个String。

您的主要方法是将ChatMsg对象发送到SessionManager actor。 SesionManager正在接收它,并通过模式匹配将其提取到字段; from和message,两者都是String类型。然后它找到相关的Session actor,并向它发送从ChatMsg对象中提取的消息。因此,它只是发送ChatMsg对象的消息部分,而不是ChatMsg对象本身。

解决它的最简单方法是在SessionManager的receive方法中进行模式匹配,绑定接收到的实际ChatMsg对象的名称,然后将其发送给Session actor。您可以通过在模式匹配前加上" name"来做到这一点。 @ pattern:

class SessionManager extends Actor{
    val system = ActorSystem("ChatSession")
    val sessions = new HashMap[String,ActorRef]
    val inbox = Inbox.create(system)

    def receive ={
        case Login(username) =>
            println(s"$username Login, now create Actor")
            val session = system.actorOf(Props(new Session(username)))
            sessions += (username->session)
            println(s"session added $sessions")
        case chatMsg @ ChatMsg(from,message) =>
            sessions(from) ! chatMsg

    }
}