0

I am using akka-http websocket client to connect with websocket server and for sending and retrieving message.

object WebSocketClientFlow {
def main(args: Array[String]) = {
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
import system.dispatcher

// Future[Done] is the materialized value of Sink.foreach,
// emitted when the stream completes
val incoming: Sink[Message, Future[Done]] =
  Sink.foreach[Message] {
    case message: TextMessage.Strict =>
      println(message.text)
  }

// send this as a message over the WebSocket
val outgoing = Source.single(TextMessage("hello world!"))

// flow to use (note: not re-usable!)
val webSocketFlow = Http().webSocketClientFlow(WebSocketRequest("ws://echo.websocket.org"))

// the materialized value is a tuple with
// upgradeResponse is a Future[WebSocketUpgradeResponse] that
// completes or fails when the connection succeeds or fails
// and closed is a Future[Done] with the stream completion from the incoming sink
val (upgradeResponse, closed) =
  outgoing
    .viaMat(webSocketFlow)(Keep.right) // keep the materialized Future[WebSocketUpgradeResponse]
    .toMat(incoming)(Keep.both) // also keep the Future[Done]
    .run()

// just like a regular http request we can access response status which is available via upgrade.response.status
// status code 101 (Switching Protocols) indicates that server support WebSockets
val connected = upgradeResponse.flatMap { upgrade =>
  if (upgrade.response.status == StatusCodes.SwitchingProtocols) {
    Future.successful(Done)
  } else {
    throw new RuntimeException(s"Connection failed: ${upgrade.response.status}")
  }
}

// in a real application you would not side effect here
connected.onComplete(println)
closed.foreach(_ => println("closed"))
}
}

This example is mentioned in akka-http documentation.

Using this example I can send only one message to a request. How can I send and retrieve multiple message on the same request?

Ayush Mishra
  • 567
  • 1
  • 7
  • 19

1 Answers1

0

You need to take a look at the half-closed socket section of the docs.

http://doc.akka.io/docs/akka/2.4.10/scala/http/client-side/websocket-support.html#Half-Closed_WebSockets

Essentially, slap a Source.maybe to your outgoing stream (subscription messages usually), and it keeps the socket from shutting down.

Brian Pendleton
  • 839
  • 4
  • 13
  • Thanks Brian for your reply. Could you please tell me how would we pass another flow with same request? val flow: Flow[Message, Message, Promise[Option[Message]]] = Flow.fromSinkAndSourceMat( Sink.foreach[Message](println), Source.maybe[Message] )(Keep.right) val (upgradeResponse, promise) = Http().singleWebSocketRequest( WebSocketRequest("ws://localhost:9000/greeter"), flow ) Now I have another message to pass. val flow1: Flow[Message, Message, Future[Done]] = Flow.fromSinkAndSourceMat(printSink, helloSource)(Keep.left) – Ayush Mishra Sep 08 '16 at 12:35
  • You could have two input sources. One ends with the source.maybe, and one is a source queue. Then you can merge the two before sending to the web socket flow. The first flow is just to connect and keep open, then you send messages to the queue that you want passed to the socket. Does that make sense? I haven't tried, it is just and idea. The merge will just take values from both and flow them along – Brian Pendleton Sep 10 '16 at 15:05
  • Thanks Brian As per your suggestion, I have created two sources. ` **val s1 = Source.maybe[Message] **` `val bufferSize = 10` `**val s2: Source[Message, SourceQueueWithComplete[Message]] = Source.queue[Message](bufferSize, OverflowStrategy.fail)**` `val flow: Flow[Message, Message, Promise[Option[Message]]] = Flow.fromSinkAndSourceMat( Sink.foreach[Message](println), s1.merge(s2) )(Keep.right)` – Ayush Mishra Sep 12 '16 at 08:12
  • After that `val wrq = WebSocketRequest("ws://localhost:9000/greeter") val (upgradeResponse, promise) = http.singleWebSocketRequest( wrq, flow )` Now I have created another source `val ss = Source(List(TextMessage("3333"), TextMessage("444")))` – Ayush Mishra Sep 12 '16 at 08:12
  • Now when I am adding this new source in queue like this `s2 ++ ss` My websocket server `ws://localhost:9000/greete` is not getting any reponse. – Ayush Mishra Sep 12 '16 at 08:14