Сокеты и потоковая передача в Play Framework

Я читаю Play-Socket.io документация и Play WebSocket документация о том, как их использовать через Akka Streams.

Я не могу понять, почему необходимо использовать Flow.fromSinkAndSource.

В документации для Play WebSockets говорится:

Обратите внимание, что хотя концептуально поток часто рассматривается как нечто, что получает сообщения, выполняет с ними некоторую обработку, а затем создает обработанные сообщения — нет никаких причин, по которым это должно быть так, вход потока может быть полностью отключен. от выхода потока. Akka streams предоставляет конструктор Flow.fromSinkAndSource именно для этой цели, и часто при обработке WebSockets вход и выход вообще не будут связаны.

Я вообще не понимаю, зачем их вообще отключать? Почему простое Flow здесь не имеет смысла?


person Omid    schedule 14.02.2018    source источник


Ответы (1)


Я не могу понять, зачем нужно использовать Flow.fromSinkAndSource....Я вообще не понимаю, почему их вообще надо отключать? Почему простое Flow здесь не имеет смысла?

В Play обработчик сообщений WebSocket представляет собой Flow[In, Out, _] (который преобразуется в/из Flow[Message, Message, Any] через MessageFlowTransformer). Если вы используете WebSockets в режиме запрос-ответ, вы можете использовать Flow[In].map или что-то с похожей семантикой для реализации этого обработчика (следующие примеры взяты из Играть в документацию):

def socket =  WebSocket.accept[String, String] { request =>

  // log the message to stdout and send response back to client
  Flow[String].map { msg =>
    println(msg)
    "I received your message: " + msg
  } // Flow[String, String, _]
}

В приведенном выше примере вход и выход связаны: вход преобразуется, а результат этого преобразования используется как выход.

WebSockets также могут быть действительно двунаправленными, что означает, что вход и выход не обязательно должны быть связаны. Это когда Flow.fromSinkAndSource вступает в игру: Sink и Source, которые передаются в этот метод, независимы. Тривиальным примером этого является обработчик, который игнорирует входящее соединение и просто отправляет одно сообщение в сокет:

def socket = WebSocket.accept[String, String] { request =>

  // Just ignore the input
  val in = Sink.ignore

  // Send a single 'Hello!' message and close
  val out = Source.single("Hello!")

  Flow.fromSinkAndSource(in, out) // Flow[String, String, _]
}

В приведенном выше примере используется Flow.fromSinkAndSource, потому что вход и выход не связаны: вход не имеет ничего общего с выходом.

Независимо от того, используете ли вы WebSockets в режиме «запрос-ответ» или по-настоящему двунаправленным, оба подхода моделируются как Flow[In, Out, _]. Если вы используете WebSockets действительно двунаправленным способом, вы можете использовать Flow.fromSinkAndSource для реализации Flow[In, Out, _].

person Jeffrey Chung    schedule 14.02.2018
comment
Спасибо. Мой первый вопрос: почему in является типом Sink, а не источником во втором примере? И если мы используем двустороннюю связь, могу ли я создать 2 разных экземпляра socket, таких как второй пример, один из которых просто получает и использует, а другой просто отправляет данные? Они идут на одну и ту же розетку? Был бы признателен, если бы вы добавили их к ответу. - person Omid; 14.02.2018
comment
Еще одно дополнение, я думаю, как будет выглядеть ответ в сценарии, когда у вас есть тип сообщения запрос/ответ, но иногда вы хотите что-то передать клиенту (например, выйти из него, уведомление), мы собираемся использовать 2 розетки? как можно повторно использовать один и тот же сокет для этого? - person Omid; 14.02.2018