我可以使用Akka I / O连接到ServerSocket
,但是当我关闭套接字时,我没有看到任何类型的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]
}
}
}
[错误]'已连接(localhost / 127.0.0.1:59141,127.0.0.1:54809)'不是'akka.io.Tcp $ ConnectionClosed'的实例(AkkaTcpTests.scala:46)
感谢您的帮助。
答案 0 :(得分:1)
查看http://doc.akka.io/docs/akka/2.2.3/scala/io-tcp.html
在收到任何进一步的TCP消息之前,您的侦听器必须使用连接注册自己:
为了激活新连接,必须是Register消息 发送给连接演员,通知一个人应该是谁 从套接字接收数据。在此步骤完成之前连接 不能使用,并有一个内部超时后, 如果没有Register消息,连接actor将自行关闭 接收。
在监听器的接收块中添加
case c @ Connected(remote, local) =>
val connection = sender
connection ! Register(self)
// change behaviour with become, notify someone, ...
编辑:正如Roland指出的那样,在给定方案中,还需要在accept()
上调用ServerSocket
,它返回一个Socket,然后调用{{1}那个是为了触发close()
消息(PeerClosed
)。如果在ServerSocket上调用instanceOf[Tcp.ConnectionClosed]
,则在关闭服务器连接时会引发错误。但通常在使用Akk IO时不必处理此级别。
答案 1 :(得分:1)
关闭ServerSocket
不会终止其接受的连接,您必须通过调用Socket
获取accept()
,然后您可以关闭该连接以拆除连接
除了Carsten给出的答案之外,还需要这样做。