早上好,我在使用TCP的基本akka IO时遇到问题
我具有akka文档中所示的客户端和服务器的基本实现:
处理程序是[SimpleEchoHandler](https://github.com/akka/akka/blob/v2.5.20/akka-docs/src/test/scala/docs/io/EchoServer.scala#L227-L304),但另一个也以相同的方式起作用。
我有一个主要的测试方法,该方法会在首次连接到服务器时停止:
package core.september
import java.net.InetSocketAddress
import akka.actor.{Actor, ActorLogging, ActorRef, ActorSystem, Props}
import akka.util.ByteString
import com.typesafe.config.ConfigFactory
import core.september.fastchain.network.Client
/**
* @author ${user.name}
*/
object App {
class ClientHandler extends Actor with ActorLogging {
def receive = {
case toLog ⇒ {
log.debug("Client received "+ toLog.toString)
}
//Thread.sleep(200)
}
}
def main(args : Array[String]) {
val config = ConfigFactory.parseString("akka.loglevel = DEBUG")
implicit val system = ActorSystem("EchoServer", config)
var clientHand:ActorRef = system.actorOf(Props(classOf[ClientHandler]))
var address:InetSocketAddress = new InetSocketAddress("localhost",5080)
var ackServer = system.actorOf(Props(classOf[EchoManager], classOf[SimpleEchoHandler],5080), "simple")
var client:ActorRef = system.actorOf(Props(classOf[Client],address,clientHand));
//Thread.sleep(200)
client ! ByteString("echo")
//Thread.sleep(200)
client ! "close"
}
}
如果我在每条消息之后都没有注释掉两个Thread.sleep,则看不到已发送消息的输出,则没有睡眠的输出就是:
[DEBUG] [02/07/2019 15:47:21.812] [EchoServer-akka.actor.default-dispatcher-4] [akka://EchoServer/system/IO-TCP/selectors/$a/0] Attempting connection to [localhost/127.0.0.1:5080]
[DEBUG] [02/07/2019 15:47:21.816] [EchoServer-akka.actor.default-dispatcher-4] [akka://EchoServer/system/IO-TCP/selectors/$a/0] Connection established to [localhost/127.0.0.1:5080]
[DEBUG] [02/07/2019 15:47:21.825] [EchoServer-akka.actor.default-dispatcher-3] [akka://EchoServer/user/$a] Client received Connected(localhost/127.0.0.1:5080,/127.0.0.1:54616)
我完全松散了ByteString消息和“关闭”消息。 我的问题是为什么我需要将主线程置于睡眠状态以显示其他消息。 正确记录了thread.sleep消息:
[DEBUG] [02/07/2019 15:53:55.988] [EchoServer-akka.actor.default-dispatcher-5] [akka://EchoServer/system/IO-TCP/selectors/$a/0] Attempting connection to [localhost/127.0.0.1:5080]
[DEBUG] [02/07/2019 15:53:55.999] [EchoServer-akka.actor.default-dispatcher-5] [akka://EchoServer/system/IO-TCP/selectors/$a/0] Connection established to [localhost/127.0.0.1:5080]
[DEBUG] [02/07/2019 15:53:56.011] [EchoServer-akka.actor.default-dispatcher-5] [akka://EchoServer/user/$a] Client received Connected(localhost/127.0.0.1:5080,/127.0.0.1:54712)
[DEBUG] [02/07/2019 15:53:56.157] [EchoServer-akka.actor.default-dispatcher-2] [akka://EchoServer/user/$a] Client received ByteString(101, 99, 104, 111)
[DEBUG] [02/07/2019 15:53:56.374] [EchoServer-akka.actor.default-dispatcher-4] [akka://EchoServer/user/$a] Client received connection closed
ClientActor实现是:
package core.september.fastchain.network
import akka.actor.{ Actor, ActorRef, Props }
import akka.io.{ IO, Tcp }
import akka.util.ByteString
import java.net.InetSocketAddress
object Client {
def props(remote: InetSocketAddress, replies: ActorRef) =
Props(classOf[Client], remote, replies)
}
class Client(remote: InetSocketAddress, listener: ActorRef) extends Actor {
import Tcp._
import context.system
import akka.io.Tcp
/*if (listener == null) {
listener = Tcp.get(context.system).manager
}*/
IO(Tcp) ! Connect(remote)
def receive = {
case CommandFailed(_: Connect) ⇒
listener ! "connect failed"
context stop self
case c @ Connected(remote, local) ⇒
listener ! c
val connection = sender()
connection ! Register(self)
context become {
case data: ByteString ⇒
connection ! Write(data)
case CommandFailed(w: Write) ⇒
// O/S buffer was full
listener ! "write failed"
case Received(data) ⇒
listener ! data
case "close" ⇒
connection ! Close
case _: ConnectionClosed ⇒
listener ! "connection closed"
context stop self
}
}
}
非常感谢。
答案 0 :(得分:2)
您必须等待演员处理您的消息,然后退出应用程序。
最简单的方法是使用Akka的gracefulStop
模式:
import akka.pattern.gracefulStop
client ! ByteString("echo")
client ! "close"
Await.result(gracefulStop(client, 1 second)(system)