Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Работа с сетью > Jetty WebSocket статус при обрыве соединения


Автор: ZVano 23.9.2016, 17:00
0. Имею рабочий WebSocketServer на "ws://localhost:8000".
Он запущен и готов к работе.
Для простоты считаем что это сервер чата.
1. Чат-клиент. Запускаю. Выполняется успешный коннект к серверу используя Jetty WebSocketClient wsClient 
2. Чат-клиент. Запрашиваю статус соединения.
wsClient.isStarted() // Возвращает true
3. Чат-сервер. Вручную выключаю.
4. Чат-клиент. Запрашиваю статус соединения
wsClient.isStarted() // Возвращает true

Класс-обертка для инициализвации соединения
Код

// Обрезанный чат-клент.
// Оставлен только метод запуска, который вызывается в п.1

import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;

public class ChatClient{
    /**
     * Таймаут соединений при простое. По-умолчанию равен длительности рабочего
     * дня.
     */
    protected long maxIdleTimeout = 8 * 60 * 60 * 1000; // HH * MM * SS * MI
    protected String wsUrl="ws://localhost:8000";
    /**
     * Это самописный класс с методами onConnect, onClose, onMessage
     * Его методы дергает Jetty
     */
    protected MyWebSocketClient ws = new MyWebSocketClient();
    protected WebSocketClient wsClient = new WebSocketClient();
    public void start() {
        add2log("Старт...");
        try {
            wsClient.setMaxIdleTimeout(this.maxIdleTimeout);
            wsClient.start();
            ClientUpgradeRequest wsRequest = new ClientUpgradeRequest();
            Future<Session> session = wsClient.connect(ws, new URI(wsUrl), wsRequest);
            Boolean isConnnected = ws.awaitConnected(10, TimeUnit.SECONDS);
            if (isConnnected) {
                add2log("Успех. Соединен с ").add2log(wsUrl);
            } else {
                add2log("Неудача. Сервер не ответил за заданное время.");
                wsClient.stop();
            }
        } catch (Exception e) {
            add2log("Неудача. Сообщение об ошибке: " + e.getMessage());
            wsClient.stop();
        }
    }
    public boolean getIsStarted() {
        add2log("getIsStarted/" + wsClient.isStarted());
        return wsClient.isStarted();
    }
}

Класс, который дергает Jetty
Код

public class MyWebSocketClient{
    @OnWebSocketClose
    public void onClose(int statusCode, String reason) throws Exception {...}
    @OnWebSocketConnect
    public void onConnect(org.eclipse.jetty.websocket.api.Session session) throws Exception {...}
    @OnWebSocketMessage
    public void onMessage(String msg) throws Exception {...}
}


Вопросы:
1. Почему после обрыва соединения вызов wsClient.isStarted() возвращает true?
2. Как правильно работать с WebSocket клиентом от Jetty, если подразумевается длительное соединение?
В родной http://www.eclipse.org/jetty/documentation/current/jetty-websocket-client-api.html приведен пример короткоживущего SimpleEchoClient приложения.
Буду премного благодарен, если кто-то запостит ссылки на примеры.

Автор: ZVano 28.9.2016, 17:43
Не знаю правильно сделал или нет, но теперь я проверяю сессию, которая приходит в onConnect моего MyWebSocketClient.


Код

// Тут session - то что пришло в onConnect
org.eclipse.jetty.websocket.api.Session session = ws.getSession();
if (session != null & session.isOpen()){
  return true;
}


Фрагмент из Session.java
Код

package org.eclipse.jetty.websocket.api;

public interface Session extends Closeable
{
    /**
     * Return true if and only if the underlying socket is open.
     * 
     * @return whether the session is open
     */
    abstract boolean isOpen();
}

Автор: ZVano 24.10.2016, 16:57
3я часть марлезонского балета - теперь статус соединения в сессии не меняется, если в момент разрыва соединения основной поток приложения был заблокирован.

Далее искуственный пример:
Код

@WebSocket(maxTextMessageSize = 64 * 1024)
public class MyWebSocketClient{
    @OnWebSocketConnect
    public void onConnect(org.eclipse.jetty.websocket.api.Session session) throws Exception {
        System.out.printf("Шаг 1. При коннекте сохраняем сессию в свойство класса.");
        this.session = session;
    }
    @OnWebSocketMessage
    public void onMessage(String msg) throws Exception {
        System.out.printf("Шаг 2. Обработка сообщения");
        System.out.printf("Шаг 2.1. Сохраняем текст сообщения.");  
        saveToStorage(msg); // Этот искуственный вызов "заморозит" приложение на минуту. На  20й секунде искуственно производится разрыв WSS соединения со стороны сервера.
        System.out.printf("Шаг 2.2. Оповещаем клиента о результате работы"); 
        if (this.session.isOpen()){
             System.out.printf("Шаг 2.2.1. isOpen = true"); 
             this.session.getRemote().sendString("{succes : 'true', message : 'Данные успешно сохранены'}");
        } else {
             System.out.printf("Шаг 2.2.2. isOpen = false"); 
        }
    }
    protected Session session;
    @OnWebSocketClose
    public void onClose(int statusCode, String reason) throws Exception {
        System.out.printf("Шаг 3. Произошел разрыв соединения/%d - %s", statusCode, reason); 
    }
}

Получим такой результат:
Код

Шаг 1. При коннекте сохраняем сессию в свойство класса.
Шаг 2.1. Сохраняем текст сообщения.
Шаг 2.2. Оповещаем клиента о результате работы
Шаг 2.2.1. isOpen = true
Шаг 3. Произошел разрыв соединения/1006 - WebSocket Read EOF


Вопрос остается прежним - Как определить состояние подключения?
Интересует готов WebSocket к передаче данных или нет.
Неприятной неожиданностью стал тот факт, что в данном случае отправка сообщения не вызывает исключения "this.session.getRemote().sendString(...)", а по документации должен свалиться.

Код

package org.eclipse.jetty.websocket.api;
public interface RemoteEndpoint {
    /**
     * Send a text message, blocking until all bytes of the message has been transmitted.
     * <p>
     * Note: this is a blocking call
     * 
     * @param text
     *            the message to be sent
     */
    void sendString(String text) throws IOException;
}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)