Как обрабатывать сообщения об отключении сокета и сердцебиении? - PullRequest
0 голосов
/ 26 апреля 2019

Что я пытаюсь сделать

У меня есть лобби с игроками, и когда кто-то покидает лобби, я хочу обновить его для каждого клиента, чтобы отображался фактический список игроков.

Что я сделал

Чтобы избежать циклических запросов от внешнего интерфейса к внутреннему, я решил использовать web sockets.Когда кто-то покидает лобби, запрос отправляется в REST api, а затем бэкэнд, после получения этого запроса, выполняет всю бизнес-логику, а затем «высовывает» это лобби, используя сокет, чтобы обновить всех клиентов в лобби.

Моя проблема

Все работает нормально, за исключением случая, когда пользователь закрывает браузер или вкладку, потому что я не могу отправить запрос в этом сценарии.(насколько я знаю, это невозможно сделать, используя javascript и beforeunload событие, onDestroy() методы и т. д.)

Мой вопрос

Это так?можно проверить на стороне сервера, отключен ли какой-либо сокет, и если да, то как я могу это сделать?Я также пытался использовать heartbeat, который отправляется из внешнего интерфейса в бэкэнд, но я не знаю, как обработать это сообщение heartbeat на стороне сервера.

Сторона сервера (весенняя загрузка)

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguartion implements WebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/api/socket")
                .setAllowedOrigins("*")
                .withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        ThreadPoolTaskScheduler te = new ThreadPoolTaskScheduler();
        te.setPoolSize(1);
        te.setThreadNamePrefix("wss-heartbeat-thread-");
        te.initialize();

        config.enableSimpleBroker("/lobby")
                .setHeartbeatValue(new long[]{0, 1000})
                .setTaskScheduler(te);
    }
}


@Controller
public class WebSocketController {

    private final SimpMessagingTemplate template;

    WebSocketController(SimpMessagingTemplate template) {
        this.template = template;
    }

    public void pokeLobby(@DestinationVariable String lobbyName, SocketMessage message) {
        this.template.convertAndSend("/lobby/"+lobbyName.toLowerCase(), message);
    }
}

Клиентская сторона

  connectToLobbyWebSocket(lobbyName: string): void {
    const ws = new SockJS(this.addressStorage.apiAddress + '/socket');
    this.stompClient = Stomp.over(ws);
    // this.stompClient.debug = null;
    const that = this;
    this.stompClient.connect({}, function () {
      that.stompClient.subscribe('/lobby/' + lobbyName, (message) => {
        if (message.body) {
          that.socketMessage.next(message.body); // do client logic
        }
      });
    });
  }

1 Ответ

1 голос
/ 26 апреля 2019

Вы можете прослушивать SessionDisconnectEvent в своем приложении и отправлять сообщения другим клиентам, когда вы получаете такое событие.

Событие возникает, когда сеанс клиента WebSocket, использующего простой протокол обмена сообщениями (например, STOMP) в качестве субпротокола WebSocket, закрыт.Обратите внимание, что это событие может быть вызвано более одного раза для одного сеанса, и поэтому потребители событий должны быть идемпотентными и игнорировать повторяющееся событие.

Существуют и другие типы событий .

...