Функциональность Android и Java Ping / Pong Web Socket - PullRequest
1 голос
/ 06 июля 2019

Я разработал Android-приложение, которое подключается к JAVA Web Socket, и в основном оно работает очень хорошо.Проблема в том, что иногда клиент отключается, но соединение на стороне сервера кажется подключенным.

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

Я подумал реализовать пинг / понг для обмена сообщениями между сервером и всеми клиентами, а в случае отсутствия ответа от клиентов - закрыть соединение на стороне сервера.

Я могу легко реализовать такой мой частный механизм, но я прочитал вокруг, и я понимаю, что в Java и Android есть встроенный механизм обмена сообщениями Ping / Pong, но я не смог найти ни одного примера этого.

Может в любом случае, приведите простой пример того, как реализовать функцию обмена сообщениями Ping / Pong с помощью встроенных инструментов?

1 Ответ

0 голосов
/ 06 июля 2019

Мне удалось реализовать функциональность Ping / Pong между EE JAVA WebSocket и приложением для Android.Сервер отправляет сообщение Ping клиенту каждые 5 минут.если сервер не получил сообщение Pong в течение 5 секунд, сервер закрывает соединение с клиентом.

вот мое решение, если кому-то понадобится:

Сторона WebSocket:

public class User {
    public ScheduledExecutorService pingExecutorService;
    public Timer disconnectTimer;
    private Session userSession;
    private String userName;

    public User(Session userSession) {
        this.userSession = userSession;
    }

    public Session getUserSession() {
        return userSession;
    }

    public void setUserSession(Session userSession) {
        this.userSession = userSession;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}

@OnOpen
public void onOpen(Session session) {
    User newUserConnection = new User(session);
    connections.getConnections().put(session.getId(), newUserConnection);
    schedulePingMessages(newUserConnection);
}

@OnClose
public void onClose(Session session) {
    handleOnClose(session);
}

@OnMessage
public void onMessage(String message, Session session) {
    messageHandler.handleMessage(message, session);
}

@OnMessage
public void onPong(PongMessage pongMessage, Session session) {
    String sourceSessionId = session.getId();
    User user = connections.getConnections().get(sourceSessionId);
    user.disconnectTimer.cancel();
    user.disconnectTimer.purge();
}

@OnError
public void onError(Throwable t) {
    System.out.println(new Date() + "onError::" + t.getMessage());
    t.printStackTrace();
}

private void schedulePingMessages(User newUserConnection) {
    newUserConnection.pingExecutorService = Executors.newScheduledThreadPool(1);
    newUserConnection.pingExecutorService.scheduleAtFixedRate(() -> {
        scheduleDiconnection(newUserConnection);
        try {
            String data = "Ping";
            ByteBuffer payload = ByteBuffer.wrap(data.getBytes());
            newUserConnection.getUserSession().getBasicRemote().sendPing(payload);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }, 300, 300, TimeUnit.SECONDS);
}

private void scheduleDiconnection(User user) {
    user.disconnectTimer = new Timer();
    user.disconnectTimer.schedule(new TimerTask() {
        @Override
        public void run() {
            try {
                user.getUserSession().close(new CloseReason(CloseCodes.UNEXPECTED_CONDITION," Client does not response"));
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }, 5000);
}

Сторона андроида просто должна добавить следующий метод переопределения:

    @Override
    public void onWebsocketPing(WebSocket conn, Framedata f) {
        Log.i("ZCF","got Ping !");
        super.onWebsocketPing(conn, f);
    }
...