spray-websocket -
Apache
跨平台
Scala
软件简介
spray-websocket 是 Spray 的扩展,实现对 WebSocket
的支持。
示例代码:
package spray.can.websocket.examples
import akka.actor.{ ActorSystem, Actor, Props, ActorLogging, ActorRef, ActorRefFactory }
import akka.io.IO
import spray.can.Http
import spray.can.server.UHttp
import spray.can.websocket
import spray.can.websocket.frame.{ BinaryFrame, TextFrame }
import spray.http.HttpRequest
import spray.can.websocket.FrameCommandFailed
import spray.routing.HttpServiceActor
object SimpleServer extends App with MySslConfiguration {
final case class Push(msg: String)
object WebSocketServer {
def props() = Props(classOf[WebSocketServer])
}
class WebSocketServer extends Actor with ActorLogging {
def receive = {
// when a new connection comes in we register a WebSocketConnection actor as the per connection handler
case Http.Connected(remoteAddress, localAddress) =>
val serverConnection = sender()
val conn = context.actorOf(WebSocketWorker.props(serverConnection))
serverConnection ! Http.Register(conn)
}
}
object WebSocketWorker {
def props(serverConnection: ActorRef) = Props(classOf[WebSocketWorker], serverConnection)
}
class WebSocketWorker(val serverConnection: ActorRef) extends HttpServiceActor with websocket.WebSocketServerWorker {
override def receive = handshaking orElse businessLogicNoUpgrade orElse closeLogic
def businessLogic: Receive = {
// just bounce frames back for Autobahn testsuite
case x @ (_: BinaryFrame | _: TextFrame) =>
sender() ! x
case Push(msg) => send(TextFrame(msg))
case x: FrameCommandFailed =>
log.error("frame command failed", x)
case x: HttpRequest => // do something
}
def businessLogicNoUpgrade: Receive = {
implicit val refFactory: ActorRefFactory = context
runRoute {
getFromResourceDirectory("webapp")
}
}
}
def doMain() {
implicit val system = ActorSystem()
import system.dispatcher
val server = system.actorOf(WebSocketServer.props(), "websocket")
IO(UHttp) ! Http.Bind(server, "localhost", 8080)
readLine("Hit ENTER to exit ...\n")
system.shutdown()
system.awaitTermination()
}
// because otherwise we get an ambiguous implicit if doMain is inlined
doMain()
}