pekko/akka-docs/rst/scala/code/docs/stream/io/StreamTcpDocSpec.scala

144 lines
3.9 KiB
Scala
Raw Normal View History

2014-12-22 16:18:26 +01:00
/**
* Copyright (C) 2014-2016 Lightbend Inc. <http://www.lightbend.com>
2014-12-22 16:18:26 +01:00
*/
package docs.stream.io
2014-12-22 16:18:26 +01:00
import java.util.concurrent.atomic.AtomicReference
import akka.stream._
2015-04-24 13:15:02 +02:00
import akka.stream.scaladsl.Tcp._
import akka.stream.scaladsl._
import akka.testkit.AkkaSpec
import akka.testkit.TestProbe
2014-12-22 16:18:26 +01:00
import akka.util.ByteString
import docs.utils.TestUtils
import scala.concurrent.Future
2014-12-22 16:18:26 +01:00
class StreamTcpDocSpec extends AkkaSpec {
implicit val ec = system.dispatcher
implicit val materializer = ActorMaterializer()
2014-12-22 16:18:26 +01:00
// silence sysout
def println(s: String) = ()
"simple server connection" in {
{
//#echo-server-simple-bind
val binding: Future[ServerBinding] =
Tcp().bind("127.0.0.1", 8888).to(Sink.ignore).run()
binding.map { b =>
b.unbind() onComplete {
case _ => // ...
}
}
//#echo-server-simple-bind
}
{
val (host, port) = TestUtils.temporaryServerHostnameAndPort()
//#echo-server-simple-handle
import akka.stream.scaladsl.Framing
2015-05-05 15:02:11 +02:00
val connections: Source[IncomingConnection, Future[ServerBinding]] =
Tcp().bind(host, port)
connections runForeach { connection =>
println(s"New connection from: ${connection.remoteAddress}")
val echo = Flow[ByteString]
.via(Framing.delimiter(
ByteString("\n"),
maximumFrameLength = 256,
allowTruncation = true))
.map(_.utf8String)
.map(_ + "!!!\n")
.map(ByteString(_))
connection.handleWith(echo)
}
//#echo-server-simple-handle
2014-12-22 16:18:26 +01:00
}
}
"initial server banner echo server" in {
val localhost = TestUtils.temporaryServerAddress()
2015-04-24 13:15:02 +02:00
val connections = Tcp().bind(localhost.getHostName, localhost.getPort) // TODO getHostString in Java7
val serverProbe = TestProbe()
2014-12-22 16:18:26 +01:00
import akka.stream.scaladsl.Framing
2014-12-22 16:18:26 +01:00
//#welcome-banner-chat-server
2015-05-05 15:02:11 +02:00
connections.runForeach { connection =>
2014-12-22 16:18:26 +01:00
// server logic, parses incoming commands
val commandParser = Flow[String].takeWhile(_ != "BYE").map(_ + "!")
2014-12-22 16:18:26 +01:00
import connection._
val welcomeMsg = s"Welcome to: $localAddress, you are: $remoteAddress!"
val welcome = Source.single(welcomeMsg)
2014-12-22 16:18:26 +01:00
val serverLogic = Flow[ByteString]
.via(Framing.delimiter(
ByteString("\n"),
maximumFrameLength = 256,
allowTruncation = true))
.map(_.utf8String)
//#welcome-banner-chat-server
.map { command serverProbe.ref ! command; command }
//#welcome-banner-chat-server
.via(commandParser)
// merge in the initial banner after parser
.merge(welcome)
.map(_ + "\n")
.map(ByteString(_))
2014-12-22 16:18:26 +01:00
connection.handleWith(serverLogic)
}
//#welcome-banner-chat-server
import akka.stream.scaladsl.Framing
2014-12-22 16:18:26 +01:00
val input = new AtomicReference("Hello world" :: "What a lovely day" :: Nil)
def readLine(prompt: String): String = {
input.get() match {
case all @ cmd :: tail if input.compareAndSet(all, tail) cmd
case _ "q"
}
}
{
//#repl-client
2015-04-24 13:15:02 +02:00
val connection = Tcp().outgoingConnection("127.0.0.1", 8888)
//#repl-client
}
{
2015-04-24 13:15:02 +02:00
val connection = Tcp().outgoingConnection(localhost)
//#repl-client
val replParser =
Flow[String].takeWhile(_ != "q")
.concat(Source.single("BYE"))
.map(elem => ByteString(s"$elem\n"))
val repl = Flow[ByteString]
.via(Framing.delimiter(
ByteString("\n"),
maximumFrameLength = 256,
allowTruncation = true))
.map(_.utf8String)
.map(text => println("Server: " + text))
.map(_ => readLine("> "))
.via(replParser)
connection.join(repl).run()
//#repl-client
}
serverProbe.expectMsg("Hello world")
serverProbe.expectMsg("What a lovely day")
serverProbe.expectMsg("BYE")
2014-12-22 16:18:26 +01:00
}
}