期货与阿卡的演员一起使用

时间:2014-04-29 18:34:13

标签: scala akka actor future

我想使用akka远程处理创建服务器/客户端系统。首先,我创建一个简单的远程服务器。 (我为了测试目的而编写了下面的代码,并澄清了我的概念,所以它确实做不了多少。)

我希望我的客户端向服务器发送用户名和密码,服务器可以验证并回复。起初我创建了一个客户端角色。从我的客户端对象,我发送此演员的用户名和密码(我在这里使用未来)。然后,客户端actor使用另一个未来将此用户名和密码发送到服务器。

我的代码中的服务器获取用户名和密码并将其打印出来。问题是我从服务器上得不到任何回报。由于我使用了将来将信息发送到服务器,因此它应该回复结果。这是我认为我有一个概念问题的地方。通过akka文档并未澄清这一点。但我确定我搞砸了一些非常基本的东西。服务器代码是:

在TrustNoOne和cmbaxter的建议后编辑。

package server


import collection.mutable
import akka.actor._
import com.typesafe.config.ConfigFactory
import shared._
import shared.CaseClass._

object Server extends App { 
val system = ActorSystem("ServerSystem",
     ConfigFactory.parseString("""
   akka {
     actor {
       provider = "akka.remote.RemoteActorRefProvider"
     }
     remote {
       netty.tcp {
         hostname = 127.0.0.1
         port = 5555
       }
     }
   }
 """))
system.actorOf(Props[ServerActorClass], "ServerActor")
}

class ServerActorClass extends Actor {
  def receive = {
    case userPass: UserPass => {
      sender ! verified()
      println(userPass)
    }
    case testMsg: String => println("Got a msg"+ testMsg)
  }
}

客户端代码是:

package client

import ...

object Client extends App {
  val system = ActorSystem("ClientSystem",
    ConfigFactory.parseString("""
   akka {
     actor {
       provider = "akka.remote.RemoteActorRefProvider"
     }
     remote {
       netty.tcp {
         hostname = 127.0.0.1
         port = 0
       }
     }
   }
  """))
  val clientActor = system.actorOf(Props[ClientActor], name = "ClientActor") //the local actor

  implicit val timout = Timeout(50 seconds)
  val f = ask(clientActor, UserPass("a","b"))
  f.onSuccess {
    case GO => println("Got something back from Client actor") //Still doesn't happen!
  }
}


class ClientActor extends Actor {

  // create the remote actor
  val server = context.actorFor("akka.tcp://ServerSystem@127.0.0.1:5555/user/ServerActor")

  implicit val timout = Timeout(1 seconds)

  def receive = {
    case a: String => println("back" + a)
    case a: UserPass => { 
      val f: Future[Any] = (server ? a) 
      f.onSuccess {
        case response: verified => {
          println("Got something back from server") //Does happen now!
          val asker = sender()
          asker ! GO()
        }
        case response: verificationFailed => {
           val asker = sender() 
           asker ! NO()
        }
      }
    }
  } 
}

客户端和服务器共享的案例类:

package shared
case object CaseClass {
  case class verified //Server msg to acknowledge user and pass successful verification
  case class verificationFailed //Server msg saying user pass verification failed
  case class GO
  case class NO
  case class UserPass(user:String, pass:String)

我想知道我做错了什么。如果有人可以解释而不是仅仅指出问题,那就太好了,因为我希望学习。

2 个答案:

答案 0 :(得分:1)

在服务器角色中,您发送响应如下:

sender ! CaseClass.verified

您实际上正在发送"已验证的"将伴侣对象归类到客户端。您应该将经过验证的类作为案例对象,或者将经过验证的实例发回给客户:

sender ! CaseClass.verified()

您正在执行其他(无关)错误:

  • 在将来的回调中关闭发件人(制作本地别名val replyTo = sender()
  • 不尊重命名惯例(大写字母等)
  • 使用deprecated" actorFor"。你必须使用actorSelection(参见akka docs)

答案 1 :(得分:1)

你没有等待回复而退出。

implicit val timout = Timeout(50 seconds)
val f: Future[Any] = clientActor ? UserPass("s","a")
f.onSuccess {
  case GO => println("Got something back from Client actor") //Doesnt happen!
}

为回调设置处理程序,但是你的程序就存在了。

最低限度,你可以scala.concurrent.Await.result(f)