我尝试使用Akka和Scala编写TCP服务器,它将实例化actor并在客户端分别连接和断开连接时停止actor。我有一个TCP绑定actor,
class Server extends Actor{
import Tcp._
import context.system
IO(Tcp) ! Bind(self, new InetSocketAddress("localhost", 9595))
def receive = {
case Bound(localAddress) =>
println("Server Bound")
println(localAddress)
case CommandFailed(_: Bind) => context stop self
case Connected(remote, local)=>
val handler = context.system.actorOf(Props[ConnHandler])
val connection = sender()
connection ! Register(handler)
}
}
以上实例化localhost:9595
上的TCP侦听器,并将处理程序actor注册到每个连接。
然后我在我的receive
类中定义了ConnHandler
def,缩写为...
,代码行为正确。
case received => {...}
case PeerClosed => {
println("Stopping")
//Other actor stopping, cleanup.
context stop self
}
(有关我曾经写过的文档,请参阅http://doc.akka.io/docs/akka/snapshot/scala/io-tcp.html - 它在PeerClosed
案例中使用的代码大致相同)
然而,当我关闭套接字客户端时,该actor仍在运行,并且没有"停止"邮件已打印。
我没有附近配置的非Windows机器来测试这个,因为我相信这与我在Windows上运行有关,因为在谷歌搜索后,我发现了一个仍然开放的bug - https://github.com/akka/akka/issues/17122 - 这指的是一些在基于Windows的系统上错过关闭事件。
我是否在代码中犯了一个愚蠢的错误,或者这是否是上面链接的错误的一部分?
虽然我可以写一个关闭连接的Received(data)
的情况,然而,网络断开连接导致的断开连接会使服务器处于不可恢复状态,需要重启应用程序,因为它会在一个说客户端仍然连接的状态下留下一个辅助共享actor,因此,服务器会拒绝该用户的进一步连接。
编辑:
我通过添加一个看门狗定时器actor来解决这个问题,该actor具有在一段时间后触发的定期动作。每次在连接上发生事件时,ConnHandler
actor都将重置监视程序计时器。虽然不理想,但它可以做我想做的事。
答案 0 :(得分:-1)
2016年12月9日编辑: 即使客户端意外断开连接,ConnHandler也会收到PeerClosed消息。