Javax Websocket因非法的UTF-8序列关闭

4

我正在使用javax.websocket API和org.glassfish.tyrus作为实现,在Java中编写Websocket客户端。

通常情况下一切正常,但有时当我接收到非常大的字符串时,连接会关闭并显示“非法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 WebSocket客户端可以完成基本的套接字字符串传输工作,不进行任何验证,并且只让我处理响应?
感谢您的反馈。

解析原因是一个选项吗? - Jordi Castilla
你能调试客户端并查看哪些字节有问题吗? - ZhongYu
我在ASP.NET WebSocket实现中遇到了同样的问题。在我的情况下,问题是由于大字符串被分割在一个表示斯堪的纳维亚字母的多字节字符的中间。请参见https://github.com/dotnet/corefx/issues/29834。Java客户端可能会有类似的问题。 - Simon Christiansen
2个回答

1
以下仅为猜测:
(1) 在服务器端,大字符串被分割成一个文本帧和一个或多个后续的连续帧。技术上,原始的大字符串被转换成字节数组,然后将字节数组分割成多个子字节数组。子数组逐一设置为帧(每个帧包含一个子字节数组)。
(2) 虽然不能保证每个子字节数组都是有效的UTF-8序列,但在服务器端或客户端上进行了有效性检查。如果确实如此,则是Tyrus的错误。 WebSocketListener of nv-websocket-client 具有帧粒度的回调方法,例如 onFrameonTextFrameonContinuationFrame 等(请注意,onTextMessageonTextFrame 是不同的),因此您可以在那里检查每个帧的字节数组。
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。谢谢。 - Ali
1
WebSocketListener有一些onXxxError()方法,例如onFrameError和onSendError。在这些方法中,onError()是一个特殊的方法。它总是在任何其他onXxxError()被调用之前被调用。例如,在ReadingThread和WritingThread的run()方法的实现中,Throwable被捕获并按照此顺序调用onError()和onUnexpectedError()。因此,虽然没有手段注册自定义异常处理程序,但您可以在onError()中处理所有错误情况。请参见WebSocketError以获取可能的错误情况。 - Takahiko Kawasaki
1
WebSocketAdapterWebSocketListener 的一个空实现。 - Takahiko Kawasaki
似乎在onTextMessage方法内触发的异常没有被设置onError方法捕获。像“意外流结束”这样的事情被捕获了,但是如果适配器的onTextMessage方法中发生NPE,则会静默失败,我必须使用常规手动日志/调试器步骤来查找原因。有什么想法吗? - Ali
哦,我明白你刚才的意思了。实现(ListenerManager)忽略了在onXxx方法内引发的任何Throwable异常。 - Takahiko Kawasaki
显示剩余3条评论

0

我刚刚遇到了同样的错误。在我将org.glassfish.tyrus版本从1.1更改为2.0.0之后,它就可以正常工作了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接