Akka 2.2.3 TCP客户端未报告ConnectionClosed

时间:2014-02-11 22:32:58

标签: scala akka

我可以使用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)

感谢您的帮助。

2 个答案:

答案 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给出的答案之外,还需要这样做。