【问题标题】:Javax Websocket closing due to Illegal UTF-8 SequenceJavax Websocket 由于非法 UTF-8 序列而关闭
【发布时间】:2015-11-19 17:14:03
【问题描述】:

我正在用 Java 编写一个 Websocket 客户端,使用 javax.websocket API,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 客户端通过套接字传输字符串并且不进行任何验证,只让我处理响应?

感谢任何反馈。

【问题讨论】:

  • 解析原因是一个选项?
  • 你能调试客户端看看哪些字节有问题吗?
  • 我在 ASP.NET websocket 实现中遇到了同样的问题。在我的例子中,问题原来是大字符串在代表斯堪的纳维亚字母的多字节字符中间被分割。见github.com/dotnet/corefx/issues/29834。 Java 客户端可能也有类似的情况。

标签: java utf-8 websocket glassfish tyrus


【解决方案1】:

我刚刚遇到了同样的错误。在我从 org.glassfish.tyrus 版本 1.1 更改为 2.0.0 后,它没有任何问题。

【讨论】:

    【解决方案2】:

    以下只是猜测。

    (1) 在服务器端,大字符串被分割成一个文本框架和一个或多个后续连续框架。从技术上讲,将原始大字符串转换为字节数组,然后将字节数组拆分为多个子字节数组。子数组一一设置为帧(= 每帧包含一个子字节数组)。

    (2) 虽然不能保证每个子字节数组都是有效的 UTF-8 序列,但无论是在服务器端还是在客户端都会进行有效性检查。如果是这样,那就是 Tyrus 的 bug。

    nv-websocket-clientWebSocketListeneronFrameonTextFrameonContinuationFrame等帧粒度的回调方法(注意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。谢谢
    • 有没有办法为 WebsocketAdapter 方法中可能发生的任何异常设置异常处理程序?
    • WebSocketListener 有一些onXxxError() 方法,例如onFrameErroronSendError。在这些方法中,onError() 是一种特殊的方法。它总是在调用任何其他 onXxxError() 之前调用。例如,在ReadingThreadWritingThreadrun()方法的实现中,Throwable被捕获,onError()onUnexpectedError()按此顺序调用。因此,虽然没有办法注册自定义异常处理程序,但您可以处理onError() 中的所有错误情况。有关可能的错误情况,请参阅WebSocketError
    • 你在哪里指定 WebsocketListener?
    • WebSocketAdapterWebSocketListener 的空实现。
    猜你喜欢
    • 1970-01-01
    • 2017-07-15
    • 1970-01-01
    • 2013-03-04
    • 1970-01-01
    • 2014-08-21
    • 1970-01-01
    • 2012-06-22
    • 1970-01-01
    相关资源
    最近更新 更多