Пожалуйста, имейте это в виду, это займет некоторое время, чтобы пройти через это, но оно должно дать вам хорошее представление о том, что делать. Примечание. Я предполагаю, что вы все еще используете Play 2.4.x и еще не обновили Play 2.5.x. А также, что вы используете Java (хотя, если вы можете переключиться, я бы рекомендовал API Akka Scala).
Шаг 1: определение актера, обрабатывающая подключение WebSocket
В контроллере можно было бы написать так:
public static WebSocket<String> socket() {
return WebSocket.withActor(MyWebSocketActor::props);
}
Это означает, что каждое соединение WebSocket будет обрабатываться актерский экземпляр типа MyWebSocketActor
. Затем вы должны реализовать актера, как это:
import akka.actor.*;
public class MyWebSocketActor extends UntypedActor {
public static Props props(ActorRef out) {
return Props.create(MyWebSocketActor.class, out);
}
private final ActorRef out;
public MyWebSocketActor(ActorRef out) {
this.out = out;
}
public void onReceive(Object message) throws Exception {
if (message instanceof String) {
out.tell("I received your message: " + message, self());
}
}
}
Параметр ActorRef out
, что вы видите на самом деле основной актер (генерируется из игры). Вам не нужно ничего с этим делать, просто помните, что как только вы отправите что-то этому актеру out
, он обработает его клиенту.
Вы также должны определить правильный путь в файле routes
:
GET /ws controllers.Application.socket()
Шаг 2: определение того, как управлять всеми WebSocket актеров
В целом у вас есть два варианта - либо вы «смотрите вверх» созданных выше субъектов, либо предоставляете какой-то механизм их управления (вид реестра)
Шаг 2.1: глядя вверх WebSocket актеров
Преимущество здесь в том, что вам не нужен дополнительный реестр/менеджер или аналогичный. Недостатком является то, что действительно сложно понять, какой актер служит для подключения к WebSocket.
Вы бы использовать actorSelection
для этого:
system.actorSelection("system/websockets/*/handler");
Это работает, потому что, как я уже говорил ранее, есть подключение актеров обработчика порождаемые Play - так их адреса, как это: akka://application/system/websockets/42/handler
. Опять же, таким образом вы можете получить всех актеров, но не одиноких (потому что вы не знаете их номер обработчика).
Шаг 2b: управление WebSocket актеры Преимущество здесь в том, что вы можете полностью управлять актерами и назначить различную информацию для них. Недостаток заключается в том, что у вас есть еще один актер, чтобы заботиться о (хотя на самом деле не проблема, Akka довольно хорошо на этом)
Вы бы создать новый актер, как:
public class ManagerActor extends UntypedActor {
List<ActorRef> slaves;
public MyWebSocketActor() {
this.slaves = new ArrayList<>();
}
public void onReceive(Object message) throws Exception {
if (message instanceof RegisterMe) {
// a new WebSocket was created so we can register him
slaves.add(sender());
// also register a DeathWatch so that we know when the WebSocket actor dies
context.watch(sender());
} else if (message instanceof Terminated) {
// remove from the list
...
}
}
}
Шаг 3: все вместе
Теперь, помните нашего актера WebSocket сверху? Ему нужно как-то зарегистрироваться у Менеджера. Опять же, вы можете сделать это двумя способами: вы можете «найти» менеджера с помощью context.system.actorSelection("user/manager")
, или если у вас уже есть ссылка (ActorRef
) менеджеру, вы можете указать ее как параметр конструктора при создании актера WebSocket
вы могли бы использовать preStart
метод, который доступен для каждого актера и сделать вашу регистрацию:
public class MyWebSocketActor extends UntypedActor {
....
@Override
public void preStart() throws Exception {
context().system().actorSelection("user/manager").tell(RegisterMe, self());
super.preStart();
}
}
Теперь, когда у вас есть все WebSocket актеров, которыми управляет ... Диспетчер, вы можете определить новые сообщения, которые он может обработать, и сказать ему, что он должен направить m4
на клиентов. Обратите внимание, что внутри Менеджера можно использовать что-то вроде Map
, где ActorRef
- это ключ, а значение - какое-то свойство пользователя или все, что вы хотите.
Почему вы беспокоитесь о 'ActorPath'? Что мешает вам просто хранить «ActorRef» где-то и использовать его для отправки ответа?Использование 'ActorRef' * - это идиоматический способ сделать это в Akka – Anton
Возможно ли сохранить ссылку актера для этого конкретного экземпляра клиента? Прошу прощения, я новичок в акке. – yukzz
Я имею в виду, что, если у вас одновременно зарегистрировано 100 пользователей, поэтому для всех тех 100 пользователей, которые могут быть использованы позже, чтобы сообщить об этом пользователям, должна быть уникальная ссылка для актера. – yukzz