1

In JavaScript and Python, two other languages I use a lot at work, it is very easy to set up a WebSocket server (or client) and send/receive messages.

For example, check out this copied code from the js WS repo. It takes just this code to set up a Node-based WebSocket server:

const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', function connection(ws) {
  ws.on('message', function incoming(message) {
    console.log('received: %s', message);
  });

  ws.send('something');
});

I can then take that ws connection object and pass it into some worker and send back messages whenever I want to. I can manually ws.send("Batch 123 Complete"), for example, and have our UI display that. No problem.

In Scala, whether I'm using http4s or akka-http, this seems like an impossibility. Maybe I'm too much of a dumb-dumb to figure it out (could be!), but I've spent time in the http4s gitter and reading tons of docs (fs2, shoot me), and the only Scala WS solutions seem to be stream-based: you take a fromClient source, a toClient source, connect them, and that's it. You can't manually do the Scala equivalent of ws.send('some info!') from the server side.

A very kind person in the http4s gitter even went so far as putting together this example to try and help me tackle what I was doing, but ultimately it seems like it doesn't. This is very much a client request -> server response setup. It can't seem to just send messages to the client whenever you want.

Have I missed something about this entirely? I hope I have, because I spent a couple of days learning http4s sockets and fs2 at work and came out with a stream-based implementation that's based on fs2's Scheduler. When a client opens a connection to my WS server, it spawns a worker and sends back status messages every second, but I don't like it :/ Required mutable variables in my code.

Any tips or discussion would be very much appreciated.

4

1 回答 1

1

我同意 HTTP4S 的例子很疯狂!

它必须是 HTTP4S 还是 Akka HTTP ?您可以使用 Java-WebSocket 库轻松完成此操作:

val s = new WebSocketServer(address) {
  override def onOpen(webSocket: WebSocket,
                      clientHandshake: ClientHandshake): Unit = {
    // keep 'webSocket' around and push messages to it
  }

  override def onClose(webSocket: WebSocket,
                       code: Int,
                       reason: String,
                       remote: Boolean): Unit = 
    // remove the reference to 'webSocket'

  override def onMessage(webSocket: WebSocket, message: String): Unit =
    println("Received something from the client")

  override def onError(webSocket: WebSocket, e: Exception): Unit = ???

  override def onStart(): Unit = ???
}

https://github.com/TooTallNate/Java-WebSocket

于 2018-04-28T19:53:36.073 回答