我正在使用javax.websocket API用Java编写Websocket客户端,并将其org.glassfish.tyrus
作为实现。
一切正常,但是有时,当我收到非常大的字符串时,连接会以神秘的“非法UTF-8序列”作为关闭原因而关闭。
log.info("Ws closed cuz: "
+ reason.getCloseCode() + " , "
+ reason.getReasonPhrase() + " , "
+ reason.toString());
输出:
INFO: Ws closed cuz: NOT_CONSISTENT , Illegal UTF-8 Sequence ,
CloseReason[1007,Illegal UTF-8 Sequence]
我猜想这是字符串太大,还是字符串包含不兼容UTF-8的任何字符。
有没有办法获取导致此问题的实际字符串/数据包/框架的更多信息?或者,如果有一种方法可以告诉tyrus忽略任何编码问题,而只将原始字符串传递给我,然后让我处理呢?
如果不是,是否还有另一个java websockets客户端,它可以通过套接字传输字符串并且不进行任何验证,只是让我处理响应?
感谢任何反馈。
以下仅是一个猜测。
(1)在服务器端,大字符串分为一个文本框和一个或多个后续的连续框。从技术上讲,原始的大字符串将转换为字节数组,然后将字节数组拆分为多个子字节数组。子数组设置为一帧一帧(=每帧包含一个子字节数组)。
(2)尽管不能保证每个子字节数组都是有效的UTF-8序列,但是可以在服务器端或客户端执行有效性检查。如果是这样,那是Tyrus的错误。
WebSocketListener
的NV-的WebSocket客户端具有在帧粒度回调方法如onFrame
,onTextFrame
,onContinuationFrame
和其他(请注意,onTextMessage
和onTextFrame
是不同的),这样就可以检查每个帧有的字节数组。
WebSocket websocket = new WebSocketFactory()
.createSocket("ws://...")
.addListener(new WebSocketAdapter() {
@Override
public void onFrame(WebSocket ws, WebSocketFrame frame) {
// If the frame is a text frame with FIN bit cleared, or
// if the frame is a continuation frame.
if ((frame.isTextFrame() && frame.getFin() == false) ||
frame.isContinuationFrame()) {
// The payload of the frame. There is no guarantee
// that this byte array is a valid UTF-8 sequence.
byte[] payload = frame.getPayload();
// Check whether the payload is a valid UTF-8 sequence
// if you want to.
checkPayload(payload);
}
}
})
.connect();
为什么不使用nv-websocket-client检查WebSocket连接中发生了什么?
是的,设置了一个断点,我看到Tyrus / Glassfish抛出了Utf8DecodeException或某些东西,但看不到是什么导致了它。我切换到您的库,到目前为止,使用onTextMessage似乎一切正常。谢谢
有没有一种方法可以为WebsocketAdapter方法中可能发生的任何异常设置异常处理程序?
WebSocketListener
有一些onXxxError()
方法,例如onFrameError
和onSendError
。在这种方法中,onError()
有一种是特殊的。它总是在调用任何其他onXxxError()
对象之前被调用。例如,在执行run()
的方法ReadingThread
和WritingThread
,Throwable
被捕获并onError()
与onUnexpectedError()
被称为顺序。因此,尽管没有注册自定义异常处理程序的方法,但是您可以在中处理所有错误情况onError()
。请参阅WebSocketError
以了解可能的错误情况。您究竟在哪里指定WebsocketListener?
WebSocketAdapter
是的空实现WebSocketListener
。