Scala Play Websocket-使用单一参与者发送Array [Byte]和String消息 [英] Scala Play Websocket - use one out actor to send both: Array[Byte] and String messages

查看:140
本文介绍了Scala Play Websocket-使用单一参与者发送Array [Byte]和String消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有Play websockets动作:

I have Play websockets action:

def socket = WebSocket.acceptWithActor[String, Array[Byte]] { request => out =>
    Props(new WebSocketInActor(out))
}

通常,我需要将大量原始数据发送到浏览器.但是有时候我需要发送一些小的字符串数据.在浏览器中,我可以检测到文本格式或原始ArrayBuffer的数据. 如果创建发送String的actor,则可以发送字符串消息;如果创建发送Array [Byte]的actor,则可以发送原始数组.两种情况下,我都不需要更改客户端代码.因此,我如何强制Play对一个演员使用两种发送方法?

Generally I need to send to browser large raw arrays of data. But sometimes I need to send some small string data. In browser I can detect is data in text format or raw ArrayBuffer. If I create actor that sends String, I can send string messages, If I create actor that sends with Array[Byte], I can send raw arrays. Both situations I don't need to change client code. So, how can I force Play to use both sending methods with one out actor?

推荐答案

啊,那些答案就在您对SO发表问题之后.通过参考和源代码查看,我发现存在混合框架FrameFromatter:

Ah, those answers that comes just after you post question on SO. Looking through reference and sourcecode, I found that there is mixedFrame FrameFromatter: https://github.com/playframework/playframework/blob/2.4.x/framework/src/play/src/main/scala/play/api/mvc/WebSocket.scala#L75

因此,您只需要说将使用Either [String,Array [Byte]]进行响应,如果要发送字符串,请使用Left(somestring),否则请使用Right [somearray].

So you just need to say that you will respond with Either[String, Array[Byte]] and if you want to send string use Left(somestring) or else use Right[somearray].

  class WebSocketInActor(out: ActorRef) extends Actor {
    override def preStart() = {
      println("User connected")
      val s = "Hello"
      out ! Left(s)
      out ! Right(s.getBytes("utf8"))
    }
    override def postStop() = {
      println("User discconnected")
    }
    def receive = {
      case msg: String => {
      }
      case _ =>
    }
  }

  def socket = WebSocket.acceptWithActor[String, Either[String, Array[Byte]]] { request => out =>
    Props(new WebSocketInActor(out))
  }

更新:

或者您可以更进一步,创建自己的帧格式化程序

Or you can go one step further and create your own frame formatter

  sealed trait WSMessage
  case class StringMessage(s: String) extends WSMessage
  case class BinaryMessage(a: Array[Byte]) extends WSMessage
  case class JsonMessage(js: JsValue) extends WSMessage

  implicit object myFrameFormatter extends BasicFrameFormatter[WSMessage] {
    private val textFrameClass = classOf[TextFrame]
    private val binaryFrameClass = classOf[BinaryFrame]

    def toFrame(message: WSMessage): BasicFrame = message match {
      case StringMessage(s) => TextFrame(s)
      case BinaryMessage(a) => BinaryFrame(a)
      case JsonMessage(js) => TextFrame(Json.stringify(js))
    }
    def fromFrame(frame: BasicFrame): WSMessage = frame match {
      case TextFrame(s) => StringMessage(s)
      case BinaryFrame(a) => BinaryMessage(a)
    }
    def fromFrameDefined(clazz: Class[_]): Boolean = clazz match {
      case `textFrameClass` => true
      case `binaryFrameClass` => true
      case _ => false // shouldn't be reachable
    }
  }

  class WebSocketInActor(out: ActorRef) extends Actor {
    override def preStart() = {
      println("User connected")
      val s = "Hello"
      val a:Array[Byte] = Array(100, 50, 30).map(_.toByte)
      out ! StringMessage(s)
      out ! JsonMessage(Json.obj("txt" -> s, "array" -> a))
      out ! BinaryMessage(a)
    }
    override def postStop() = {
      println("User discconnected")
    }
    def receive = {
      case msg: String => {
      }
      case _ =>
    }
  }

  def socket = WebSocket.acceptWithActor[String, WSMessage] { request => out =>
    Props(new WebSocketInActor(out))
  }

这篇关于Scala Play Websocket-使用单一参与者发送Array [Byte]和String消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆