2014-01-07 15:50:36 +01:00
|
|
|
/**
|
2015-03-07 22:58:48 -08:00
|
|
|
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
|
2014-01-07 15:50:36 +01:00
|
|
|
*/
|
|
|
|
|
package docs.io
|
|
|
|
|
|
|
|
|
|
import akka.actor.{ ActorRef, ActorLogging, Props, Actor, ActorSystem }
|
|
|
|
|
import akka.io.Tcp._
|
|
|
|
|
import akka.io.{ Tcp, IO }
|
|
|
|
|
import java.net.InetSocketAddress
|
|
|
|
|
import akka.testkit.{ ImplicitSender, TestProbe, AkkaSpec }
|
|
|
|
|
import akka.util.ByteString
|
|
|
|
|
|
2014-08-25 15:49:28 +02:00
|
|
|
import scala.concurrent.Await
|
|
|
|
|
import scala.concurrent.duration.Duration
|
|
|
|
|
|
2014-01-07 15:50:36 +01:00
|
|
|
object PullReadingExample {
|
|
|
|
|
|
|
|
|
|
class Listener(monitor: ActorRef) extends Actor {
|
|
|
|
|
|
|
|
|
|
import context.system
|
|
|
|
|
|
|
|
|
|
override def preStart: Unit =
|
|
|
|
|
//#pull-mode-bind
|
|
|
|
|
IO(Tcp) ! Bind(self, new InetSocketAddress("localhost", 0), pullMode = true)
|
|
|
|
|
//#pull-mode-bind
|
|
|
|
|
|
|
|
|
|
def receive = {
|
|
|
|
|
//#pull-accepting
|
|
|
|
|
case Bound(localAddress) =>
|
|
|
|
|
// Accept connections one by one
|
2014-06-20 23:05:51 +02:00
|
|
|
sender() ! ResumeAccepting(batchSize = 1)
|
|
|
|
|
context.become(listening(sender()))
|
2014-01-07 15:50:36 +01:00
|
|
|
//#pull-accepting
|
|
|
|
|
monitor ! localAddress
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//#pull-accepting-cont
|
|
|
|
|
def listening(listener: ActorRef): Receive = {
|
|
|
|
|
case Connected(remote, local) =>
|
2014-06-20 23:05:51 +02:00
|
|
|
val handler = context.actorOf(Props(classOf[PullEcho], sender()))
|
|
|
|
|
sender() ! Register(handler, keepOpenOnPeerClosed = true)
|
2014-01-07 15:50:36 +01:00
|
|
|
listener ! ResumeAccepting(batchSize = 1)
|
|
|
|
|
}
|
|
|
|
|
//#pull-accepting-cont
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case object Ack extends Event
|
|
|
|
|
|
|
|
|
|
class PullEcho(connection: ActorRef) extends Actor {
|
|
|
|
|
|
|
|
|
|
//#pull-reading-echo
|
|
|
|
|
override def preStart: Unit = connection ! ResumeReading
|
|
|
|
|
|
|
|
|
|
def receive = {
|
|
|
|
|
case Received(data) => connection ! Write(data, Ack)
|
|
|
|
|
case Ack => connection ! ResumeReading
|
|
|
|
|
}
|
|
|
|
|
//#pull-reading-echo
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class PullReadingSpec extends AkkaSpec with ImplicitSender {
|
|
|
|
|
|
|
|
|
|
"demonstrate pull reading" in {
|
|
|
|
|
val probe = TestProbe()
|
|
|
|
|
system.actorOf(Props(classOf[PullReadingExample.Listener], probe.ref), "server")
|
|
|
|
|
val listenAddress = probe.expectMsgType[InetSocketAddress]
|
|
|
|
|
|
|
|
|
|
//#pull-mode-connect
|
|
|
|
|
IO(Tcp) ! Connect(listenAddress, pullMode = true)
|
|
|
|
|
//#pull-mode-connect
|
|
|
|
|
expectMsgType[Connected]
|
|
|
|
|
val connection = lastSender
|
|
|
|
|
|
|
|
|
|
val client = TestProbe()
|
|
|
|
|
client.send(connection, Register(client.ref))
|
|
|
|
|
client.send(connection, Write(ByteString("hello")))
|
|
|
|
|
client.send(connection, ResumeReading)
|
|
|
|
|
client.expectMsg(Received(ByteString("hello")))
|
|
|
|
|
|
2014-08-25 15:49:28 +02:00
|
|
|
Await.ready(system.terminate(), Duration.Inf)
|
2014-01-07 15:50:36 +01:00
|
|
|
}
|
|
|
|
|
}
|