如何处理 websocket @OnError

How to handle websocket @OnError

除了记录错误之外,处理 websocket 错误的正确方法是什么?

关于 onError(),端点 documentation 指出:

Developers may implement this method when the web socket session creates some kind of error that is not modeled in the web socket protocol. This may for example be a notification that an incoming message is too big to handle, or that the incoming message could not be encoded.

There are a number of categories of exception that this method is (currently) defined to handle:

  • connection problems, for example, a socket failure that occurs before the web socket connection can be formally closed. These are modeled as SessionExceptions

  • runtime errors thrown by developer created message handlers calls.

  • conversion errors encoding incoming messages before any message handler has been called. These are modeled as DecodeExceptions

是否所有这些类型的异常都是致命的,导致 websocket 关闭?

如果发生错误onError()方法是否应该关闭websocket(调用Session.close())?

到目前为止,我认为我有责任彻底关闭会话,并告知客户关闭原因。这就是为什么我的 onError() 尝试在 session.isOpen() 返回 true 时调用 session.close(),但这导致 tomcat (8.0.15) 抛出 NullPointerException:

...
Caused by: java.lang.NullPointerException
    at org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.onWritePossible(WsRemoteEndpointImplServer.java:96)
    at org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.doWrite(WsRemoteEndpointImplServer.java:81)
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.writeMessagePart(WsRemoteEndpointImplBase.java:444)
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessage(WsRemoteEndpointImplBase.java:335)
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessageBlock(WsRemoteEndpointImplBase.java:264)
    at org.apache.tomcat.websocket.WsSession.sendCloseMessage(WsSession.java:536)
    at org.apache.tomcat.websocket.WsSession.doClose(WsSession.java:464)
    at org.apache.tomcat.websocket.WsSession.close(WsSession.java:441)
    at my.package.MyEndpoint.onWebSocketError(MyEndpoint.java:229)
    ... 18 more

这是 tomcat 错误、我的误解,还是两者兼而有之?

编辑: Java EE websocket 示例 dukeeetf2 似乎假定错误是致命的;并且无需关闭会话。记录错误,并删除会话:

@OnError
public void error(Session session, Throwable t) {
    /* Remove this connection from the queue */
    queue.remove(session);
    logger.log(Level.INFO, t.toString());
    logger.log(Level.INFO, "Connection error.");
}

@OnError方法调用并不意味着Session会被关闭;你可以做任何你想做的,这取决于你的应用程序指定的合同。

tomcat 实现的堆栈跟踪似乎是一个错误。

ad dukeeetf2 示例 - 似乎此代码包含其他假设 - 端点不会引发异常,因此此处捕获的所有内容都来自底层 WebSocket 框架实现。这并不意味着有 "Connection Error";我可能会立即关闭(如果这是我不希望我的应用程序处理错误的方式);此实现可能会导致在没有任何消息的情况下打开连接。

我看到这有点过时,但今天在寻找此信息时最终来到这里。 根据您对 websocket 状态的依赖程度,您需要手动关闭会话,至少对于 javax.websocket 实施。

在我的例子中,发生的错误导致了网络会话客户端管理实现的问题,所以我像上面的例子一样关闭了会话。 我认为这取决于你需要什么,但它在这个实现中肯定不会关闭会话。