4

我正在用 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 客户端可以通过套接字传输字符串并且不进行任何验证,只让我处理响应?

感谢任何反馈。

4

2 回答 2

1

以下只是猜测。

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

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

WebSocketListenernv-websocket-client具有帧粒度的回调方法,例如onFrame,等(注意和不同),因此您可以在那里检查每个帧的字节数组。onTextFrameonContinuationFrameonTextMessageonTextFrame

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 连接中发生了什么?

于 2015-08-26T04:45:00.870 回答
0

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

于 2020-12-20T11:57:15.803 回答