我正在嘗試使用Akka和Scala編寫TCP服務器,它將實例化actors並在客戶端分別連接和斷開連接時停止actor。我有一個TCP結合演員,Akka/Scala檢測到關閉的TCP連接?
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監聽器和註冊的處理程序的演員給每個連接。
然後,我在我的ConnHandler
類中定義了receive
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
情況下或多或少相同的代碼)
然而,當我關閉套接字客戶端,演員遺體運行,並且不打印「停止」消息。
我沒有附近配置的非Windows機器來測試這一點,因爲我相信這與我在Windows上運行有關,因爲在Google搜索後,我發現了一個仍然存在的問題 - https://github.com/akka/akka/issues/17122 - 它引用了一些Close事件錯過了基於Windows的系統。
我在代碼中犯了一個愚蠢的錯誤,還是會成爲上面鏈接的錯誤的一部分?
儘管我可以在關閉連接的情況下寫入Received(data)
,但是,由於網絡斷開或其他原因導致的斷開連接會使服務器處於不可恢復的狀態,因此需要重新啓動應用程序,因爲它會留下一個次要的,共享的角色,表示客戶端仍然連接,因此服務器會拒絕來自該用戶的進一步連接。
編輯:
我已經通過添加具有一定的時間後觸發一個週期性的動作看門狗定時器演員圍繞這個工作。每當連接發生事件時,ConnHandler
actor都會重置看門狗定時器。雖然不理想,但它做我想做的事。