fix some warts in IO
- remove TcpPipelineHandler’s type parameter - remove not-accept() failure test (which is completely bogus) - add comments explaining more about TcpPipelineHandler.Init - remove the funny “manager” from the Server example
This commit is contained in:
parent
f3f55d4972
commit
025a91ecc2
5 changed files with 30 additions and 36 deletions
|
|
@ -483,28 +483,6 @@ class TcpConnectionSpec extends AkkaSpec("akka.io.tcp.register-timeout = 500ms")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test is disabled on windows, as the assumption that not calling accept on a server socket means that
|
|
||||||
// no TCP level connection has been established with the client does not hold.
|
|
||||||
// RK: I think Windows is no different than any other OS in this regard, there was just a sleep() missing.
|
|
||||||
"report failed connection attempt while not accepted" in new UnacceptedConnectionTest {
|
|
||||||
run {
|
|
||||||
ignoreIfWindows()
|
|
||||||
|
|
||||||
// close instead of accept
|
|
||||||
localServerChannel.close()
|
|
||||||
|
|
||||||
// must give the OS some time to send RST from server to client
|
|
||||||
Thread.sleep(100)
|
|
||||||
|
|
||||||
EventFilter[SocketException](occurrences = 1) intercept {
|
|
||||||
selector.send(connectionActor, ChannelConnectable)
|
|
||||||
userHandler.expectMsg(CommandFailed(Connect(serverAddress)))
|
|
||||||
}
|
|
||||||
|
|
||||||
verifyActorTermination(connectionActor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val UnboundAddress = temporaryServerAddress()
|
val UnboundAddress = temporaryServerAddress()
|
||||||
|
|
||||||
"report failed connection attempt when target is unreachable" in
|
"report failed connection attempt when target is unreachable" in
|
||||||
|
|
|
||||||
|
|
@ -134,9 +134,9 @@ class TcpPipelineHandler[Ctx <: PipelineContext, Cmd, Evt](
|
||||||
* that are not Receive events will be passed directly to the handler registered for TcpPipelineHandler.
|
* that are not Receive events will be passed directly to the handler registered for TcpPipelineHandler.
|
||||||
* @tparam Ctx
|
* @tparam Ctx
|
||||||
*/
|
*/
|
||||||
class TcpReadWriteAdapter[Ctx <: PipelineContext] extends PipelineStage[Ctx, ByteString, Tcp.Command, ByteString, Tcp.Event] {
|
class TcpReadWriteAdapter extends PipelineStage[PipelineContext, ByteString, Tcp.Command, ByteString, Tcp.Event] {
|
||||||
|
|
||||||
override def apply(ctx: Ctx) = new PipePair[ByteString, Tcp.Command, ByteString, Tcp.Event] {
|
override def apply(ctx: PipelineContext) = new PipePair[ByteString, Tcp.Command, ByteString, Tcp.Event] {
|
||||||
|
|
||||||
override val commandPipeline = {
|
override val commandPipeline = {
|
||||||
data: ByteString ⇒ ctx.singleCommand(Tcp.Write(data))
|
data: ByteString ⇒ ctx.singleCommand(Tcp.Write(data))
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,7 @@ class DemoActor extends Actor {
|
||||||
}
|
}
|
||||||
|
|
||||||
//#server
|
//#server
|
||||||
object Server {
|
class Server extends Actor {
|
||||||
def apply(manager: ActorRef) = Props(classOf[Server], manager)
|
|
||||||
}
|
|
||||||
|
|
||||||
class Server(manager: ActorRef) extends Actor {
|
|
||||||
|
|
||||||
import Tcp._
|
import Tcp._
|
||||||
import context.system
|
import context.system
|
||||||
|
|
@ -38,12 +34,17 @@ class Server(manager: ActorRef) extends Actor {
|
||||||
IO(Tcp) ! Bind(self, new InetSocketAddress("localhost", 0))
|
IO(Tcp) ! Bind(self, new InetSocketAddress("localhost", 0))
|
||||||
|
|
||||||
def receive = {
|
def receive = {
|
||||||
case b @ Bound(localAddress) ⇒ manager ! b
|
case b @ Bound(localAddress) ⇒
|
||||||
|
//#do-some-logging-or-setup
|
||||||
|
context.parent ! b
|
||||||
|
//#do-some-logging-or-setup
|
||||||
|
|
||||||
case CommandFailed(_: Bind) ⇒ context stop self
|
case CommandFailed(_: Bind) ⇒ context stop self
|
||||||
|
|
||||||
case c @ Connected(remote, local) ⇒
|
case c @ Connected(remote, local) ⇒
|
||||||
manager ! c
|
//#server
|
||||||
|
context.parent ! c
|
||||||
|
//#server
|
||||||
val handler = context.actorOf(Props[SimplisticHandler])
|
val handler = context.actorOf(Props[SimplisticHandler])
|
||||||
val connection = sender
|
val connection = sender
|
||||||
connection ! Register(handler)
|
connection ! Register(handler)
|
||||||
|
|
@ -97,8 +98,15 @@ class Client(remote: InetSocketAddress, listener: ActorRef) extends Actor {
|
||||||
|
|
||||||
class IODocSpec extends AkkaSpec {
|
class IODocSpec extends AkkaSpec {
|
||||||
|
|
||||||
|
class Parent extends Actor {
|
||||||
|
context.actorOf(Props[Server], "server")
|
||||||
|
def receive = {
|
||||||
|
case msg ⇒ testActor forward msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
"demonstrate connect" in {
|
"demonstrate connect" in {
|
||||||
val server = system.actorOf(Server(testActor), "server1")
|
val server = system.actorOf(Props(classOf[Parent], this), "parent")
|
||||||
val listen = expectMsgType[Tcp.Bound].localAddress
|
val listen = expectMsgType[Tcp.Bound].localAddress
|
||||||
val client = system.actorOf(Client(listen, testActor), "client1")
|
val client = system.actorOf(Client(listen, testActor), "client1")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -427,6 +427,7 @@ Accepting connections
|
||||||
^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
.. includecode:: code/docs/io/IODocSpec.scala#server
|
.. includecode:: code/docs/io/IODocSpec.scala#server
|
||||||
|
:exclude: do-some-logging-or-setup
|
||||||
|
|
||||||
To create a TCP server and listen for inbound connections, a :class:`Bind`
|
To create a TCP server and listen for inbound connections, a :class:`Bind`
|
||||||
command has to be sent to the TCP manager. This will instruct the TCP manager
|
command has to be sent to the TCP manager. This will instruct the TCP manager
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ class SslTlsSupportSpec extends AkkaSpec {
|
||||||
val init = new TcpPipelineHandler.Init(
|
val init = new TcpPipelineHandler.Init(
|
||||||
new StringByteStringAdapter >>
|
new StringByteStringAdapter >>
|
||||||
new DelimiterFraming(maxSize = 1024, delimiter = ByteString('\n'), includeDelimiter = true) >>
|
new DelimiterFraming(maxSize = 1024, delimiter = ByteString('\n'), includeDelimiter = true) >>
|
||||||
new TcpReadWriteAdapter[HasLogging] >>
|
new TcpReadWriteAdapter >>
|
||||||
new SslTlsSupport(sslEngine(connected.remoteAddress, client = true))) {
|
new SslTlsSupport(sslEngine(connected.remoteAddress, client = true))) {
|
||||||
override def makeContext(actorContext: ActorContext): HasLogging = new HasLogging {
|
override def makeContext(actorContext: ActorContext): HasLogging = new HasLogging {
|
||||||
override def getLogger = system.log
|
override def getLogger = system.log
|
||||||
|
|
@ -148,9 +148,16 @@ class SslTlsSupportSpec extends AkkaSpec {
|
||||||
val init =
|
val init =
|
||||||
new TcpPipelineHandler.Init(
|
new TcpPipelineHandler.Init(
|
||||||
new StringByteStringAdapter >>
|
new StringByteStringAdapter >>
|
||||||
new DelimiterFraming(maxSize = 1024, delimiter = ByteString('\n'), includeDelimiter = true) >>
|
new DelimiterFraming(maxSize = 1024, delimiter = ByteString('\n'),
|
||||||
new TcpReadWriteAdapter[HasLogging] >>
|
includeDelimiter = true) >>
|
||||||
|
new TcpReadWriteAdapter >>
|
||||||
new SslTlsSupport(sslEngine(remote, client = false))) {
|
new SslTlsSupport(sslEngine(remote, client = false))) {
|
||||||
|
/*
|
||||||
|
* When creating an `Init` the abstract `makeContext` method needs to be
|
||||||
|
* implemented. If the type of the returned context does not satisfy the
|
||||||
|
* requirements of all pipeline stages, then you’ll get an error that
|
||||||
|
* `makeContext` has an incompatible type.
|
||||||
|
*/
|
||||||
override def makeContext(actorContext: ActorContext): HasLogging =
|
override def makeContext(actorContext: ActorContext): HasLogging =
|
||||||
new HasLogging {
|
new HasLogging {
|
||||||
override def getLogger = log
|
override def getLogger = log
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue