Java Websocket 文本帧长度 >=128 时出错?

标签 java websocket

我正在尝试重新发明轮子并创建我自己的 websocket 服务器。它在 Google Chrome 和 Firefox 上都可以正常连接,并且可以正确接收和回显长度最多为 127 个字符的文本帧。然而,除此之外,谷歌给了我以下错误:

与“ws://localhost:9999/”的 WebSocket 连接失败:必须使用最小字节数来编码长度

Firefox 有时会接收/解释前几个字符,然后失败代码:1006。

服务器显示正在完整接收消息并尝试完整广播它,没有运行时错误或。它也将进入 16 位长度创建器,如我的 System.out.println() 所示。我的服务器上的 java 控制台显示:

websocket 服务器已启动 客户端已连接 收到消息 1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij12345678 广播:1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij12345678 第二个数据

我目前正在编写一个帧测试器来测试我通过广播发送的帧,但希望社区能够为我节省一些跑腿工作。真正奇怪的是 126 和 127 有效负载长度有效并反射(reflect)使用 2 个字节的长度。

public void broadcast(String mess) throws IOException {
        System.out.println("broadcasting: "+mess);
        byte[] rawData = mess.getBytes();

        int frameCount = 0;
        byte[] frame = new byte[10];

        frame[0] = (byte) 129;

        if (rawData.length <= 125) {
            frame[1] = (byte) rawData.length;
            frameCount = 2;
        } else if (rawData.length >= 126 && rawData.length <= 65535) {
            System.out.println("2nd data");
            frame[1] = (byte) 126;
            byte len = (byte) rawData.length;
            frame[2] = (byte) ((len >> 8) & (byte) 255);
            frame[3] = (byte) (len & (byte) 255);                
            frameCount = 4;
        } else {
            System.out.println("3rd data");
            frame[1] = (byte) 127;
            byte len = (byte) rawData.length;
            frame[2] = (byte) ((len >> 56) & (byte) 255);
            frame[3] = (byte) ((len >> 48) & (byte) 255);
            frame[4] = (byte) ((len >> 40) & (byte) 255);
            frame[5] = (byte) ((len >> 32) & (byte) 255);
            frame[6] = (byte) ((len >> 24) & (byte) 255);
            frame[7] = (byte) ((len >> 16) & (byte) 255);
            frame[8] = (byte) ((len >> 8) & (byte) 255);
            frame[9] = (byte) (len & (byte) 255);
            frameCount = 10;
        }

        int bLength = frameCount + rawData.length;

        byte[] reply = new byte[bLength];

        int bLim = 0;
        for (int i = 0; i < frameCount; i++) {
            reply[bLim] = frame[i];
            bLim++;
        }
        for (int i = 0; i < rawData.length; i++) {
            reply[bLim] = rawData[i];
            bLim++;
        }
        for (OutputStream writer : writers) {
            writer.write(reply);   
            writer.flush();
        }            

    }

感谢社区提供的任何帮助。

最佳答案

一些注释。

  1. 您对长度的处理不当
  2. 您没有正确地将字符串转换为字节(必须通过 UTF-8 完成)

这是一个简单的示例。

以下代码已获得许可:Eclipse Public License 1.0

package websocket;

import java.nio.ByteBuffer;
import java.nio.charset.Charset;

public class RawGenerate
{
    /**
     * The overhead (maximum) for a framing header. Assuming a maximum sized payload with masking key.
     */
    public static final int OVERHEAD = 28;

    public ByteBuffer asClientInitiatedTextFrame(String msg)
    {
        ByteBuffer buf = ByteBuffer.allocate(msg.length() + OVERHEAD);
        putOpFin(buf,(byte)0x01,true);
        byte mask[] = new byte[] { 1, 2, 3, 4 }; // Needs to be random
        byte payload[] = msg.getBytes(Charset.forName("UTF-8")); // must be UTF-8 (per spec)
        putLengthAndMask(buf,payload.length,mask);
        for (int i = 0; i < payload.length; i++)
        {
            buf.put((byte)(payload[i] ^= mask[i % 4]));
        }
        buf.flip();
        return buf;
    }

    public static void putOpFin(ByteBuffer buf, byte opcode, boolean fin)
    {
        byte b = 0x00;
        if (fin)
        {
            b |= 0x80;
        }
        b |= opcode & 0x0F;
        buf.put(b);
    }

    public static void putLengthAndMask(ByteBuffer buf, int length, byte mask[])
    {
        if (mask != null)
        {
            assert (mask.length == 4);
            putLength(buf,length,(mask != null));
            buf.put(mask);
        }
        else
        {
            putLength(buf,length,false);
        }
    }

    public static void putLength(ByteBuffer buf, int length, boolean masked)
    {
        if (length < 0)
        {
            throw new IllegalArgumentException("Length cannot be negative");
        }
        byte b = (masked?(byte)0x80:0x00);

        if (length > 0xFF_FF)
        {
            buf.put((byte)(b | 0x7F));
            buf.put((byte)0x00);
            buf.put((byte)0x00);
            buf.put((byte)0x00);
            buf.put((byte)0x00);
            buf.put((byte)((length >> 24) & 0xFF));
            buf.put((byte)((length >> 16) & 0xFF));
            buf.put((byte)((length >> 8) & 0xFF));
            buf.put((byte)(length & 0xFF));
        }
        else if (length >= 0x7E)
        {
            buf.put((byte)(b | 0x7E));
            buf.put((byte)(length >> 8));
            buf.put((byte)(length & 0xFF));
        }
        else
        {
            buf.put((byte)(b | length));
        }
    }
}

关于Java Websocket 文本帧长度 >=128 时出错?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18368235/

相关文章:

java - 使用 XOM 创建 XML 时减少代码冗余

Java Swing : Ghost text showing up when updating text on a JTextArea with partially transparent background

java - Maven Checkstyle 和有效的 POM

Python 3.1 - 在 Blender 中添加库时出错

spring - Tomcat 7.0.47+ Websocket 故障转移

go - 响应没有实现 http.Hijacker

java - 由于错误代码 : Failed to find configured root that contains,无法使用共享图像按钮

java - 具有 stomp 安全性的 Spring websocket - 每个用户都可以订阅任何其他用户队列?

ruby-on-rails - 如何更改 Action 电缆 rails 中的 ping 间隔

java - Thymeleaf - 错误解析模板 "email-inlineimage.html"