2014-02-11 59 views
1

我可以使用Akka I/O連接到ServerSocket,但是當我關閉套接字時,我沒有看到任何種類的ConnectionClosed消息返回。Akka 2.2.3 TCP客戶端未報告ConnectionClosed

第一測試通過,但第二個不(與兩個2.2.3和2.3.0-RC2):

import org.specs2.mutable._ 

import java.net._ 

import akka.actor.{Actor, ActorRef, ActorSystem} 
import akka.io._ 
import akka.testkit.TestActorRef 

object System { 
    implicit val system = ActorSystem("SocketListenerTests") 
} 
import System._ 

class Listener extends Actor { 
    val manager = IO(Tcp) 

    private var _last: Any = null 
    def last = _last 

    def receive = { 
    case a: Any => _last = a 
    } 

    def connect(addr: InetSocketAddress) { manager ! Tcp.Connect(addr) } 
} 

class AkkaTcpTests extends Specification { 
    override def is = args(sequential = true)^super.is 

    val socket = new ServerSocket(0) 
    val addr = new InetSocketAddress("localhost", socket.getLocalPort) 

    def pause { Thread.sleep(200) } 

    val listener = TestActorRef[Listener].underlyingActor 

    "Akka TCP I/O" should { 
    "open connections" in { 
     listener.connect(addr) 
     pause 
     listener.last must beAnInstanceOf[Tcp.Connected] 
    } 
    "notify when server sockets are closed" in { 
     socket.close 
     pause 
     listener.last must beAnInstanceOf[Tcp.ConnectionClosed] 
    } 
    } 
} 

[錯誤]「連接(本地主機/ 127.0.0.1:59141 ,/ 127.0.0.1:54809)'不是'akka.io.Tcp $ ConnectionClosed'的實例(AkkaTcpTests.scala:46)

感謝您的任何幫助。

回答

1

看一看http://doc.akka.io/docs/akka/2.2.3/scala/io-tcp.html

你的聽衆有收到任何進一步的TCP消息之前本身就帶有連接註冊:

爲了激活新連接的註冊信息必須是 發給連接參與者,告知一個人應該從套接字接收數據。之前這一步完成連接 不能使用,並且有一個內部後的超時時間 連接演員將自行關閉,如果沒有註冊的消息是收到 。

在收到聽衆的塊添加一個

case c @ Connected(remote, local) => 
    val connection = sender 
    connection ! Register(self) 
    // change behaviour with become, notify someone, ... 

編輯:羅蘭指出,在給定的情景人們還需要調用accept()ServerSocket,它返回一個插座,並致電close()那一個爲了觸發PeerClosed消息(這是一個instanceOf[Tcp.ConnectionClosed])。如果您在ServerSocket上調用close(),則在關閉服務器連接時會引發錯誤。但是通常在使用Akk IO時你不必處理這個級別。

1

關閉ServerSocket不會終止已接受的連接,您必須通過調用accept()來獲得Socket,然後可以關閉該連接以斷開連接。

這是必要的,除了由卡斯滕給出了答案。