Как правильно закрыть веб-сокет и предоставить клиенту чистый, информативный ответ, когда на моем сервере возникает внутренняя ошибка? В моем текущем случае клиент должен предоставить параметр при подключении, и я пытаюсь обработать неправильные или отсутствующие параметры, полученные OnOpen.
Этот пример предполагает, что я могу просто создать исключение в OnOpen, которое в конечном итоге вызовет OnError, где я могу закрыть его с указанием причины и сообщения. Вроде работает, но клиент получает только EOF, 1006, CLOSE_ABNORMAL.
Кроме того, поскольку я не нашел другого обсуждения, я не могу сказать, что может быть лучшей практикой.
Я использую спецификацию JSR-356 следующим образом:
@ClientEndpoint
@ServerEndpoint(value="/ws/events/")
public class WebSocketEvents
{
private javax.websocket.Session session;
private long token;
@OnOpen
public void onWebSocketConnect(javax.websocket.Session session) throws BadRequestException
{
logger.info("WebSocket connection attempt: " + session);
this.session = session;
// this throws BadRequestException if null or invalid long
// with short detail message, e.g., "Missing parameter: token"
token = HTTP.getRequiredLongParameter(session, "token");
}
@OnMessage
public void onWebSocketText(String message)
{
logger.info("Received text message: " + message);
}
@OnClose
public void onWebSocketClose(CloseReason reason)
{
logger.info("WebSocket Closed: " + reason);
}
@OnError
public void onWebSocketError(Throwable t)
{
logger.info("WebSocket Error: ");
logger.debug(t, t);
if (!session.isOpen())
{
logger.info("Throwable in closed websocket:" + t, t);
return;
}
CloseCode reason = t instanceof BadRequestException ? CloseReason.CloseCodes.PROTOCOL_ERROR : CloseReason.CloseCodes.UNEXPECTED_CONDITION;
try
{
session.close(new CloseReason(reason, t.getMessage()));
}
catch (IOException e)
{
logger.warn(e, e);
}
}
}
Редактировать: Генерация исключения для связанного примера кажется странной, поэтому теперь я перехватываю исключение в OnOpen и немедленно делаю
session.close(new CloseReason(CloseReason.CloseCodes.CANNOT_ACCEPT, "some text"));
Редактировать: Это оказалось правильным, хотя отдельная ошибка на некоторое время замаскировала это.
Edit2: Пояснение: HTTP
— это мой собственный статический служебный класс. HTTP.getRequiredLongParameter()
получает параметры запроса из первоначального запроса клиента, используя
session.getRequestParameterMap().get(name)
и выполняет дальнейшую обработку.
OnOpen
закрывает сеанс до вызоваOnError
? Вы видите, что"Throwable in closed websocket"
регистрируется? - person Remy Lebeau   schedule 02.09.2017ServerEndpoint
иClientEndpoint
одновременно? Если вы не хотите использовать фильтр, вы также можете рассмотреть пользовательскую конфигурацию, в которой вы проверите, есть ли параметр здесь или нет, и какое значение он имеет. - person Al-un   schedule 09.09.2017ClientEndpoint
было объединено сServerEndpoint
в первом примере, который я нашел. Спасибо за указание; удален сейчас. - person Saturn5   schedule 09.09.2017