长度大于等于 128 的 Java Websocket 文本帧错误? [英] Java Websocket Text Frame Error at length >=128?

查看:31
本文介绍了长度大于等于 128 的 Java Websocket 文本帧错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to reinvent the wheel and create my own websocket server. It is connecting fine on both Google Chrome and Firefox and will receive and echo text frames correctly up to 127 characters in length. However, beyond that Google gives me the following error:

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

WebSocket connection to 'ws://localhost:9999/' failed: The minimal number of bytes MUST be used to encode the length

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

Firefox will receive/interpret the first few characters sometimes then fail code:1006.

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

The server shows to be receiving the message in full and attempting to broadcast it in full with no run-time errors or . It's also going to the 16 bit length creator as shown by my System.out.println(). My java console from server reads:

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

websocket server started client connected message received 1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij12345678 broadcasting: 1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij12345678 2nd data

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

I'm currently writing a frame tester to test the frame I'm sending with broadcast but was hoping the community might be able to save me some of that leg work. The really odd thing is 126 and 127 payload lengths work and reflect using the 2 bytes for length.

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));
        }
    }
}

这篇关于长度大于等于 128 的 Java Websocket 文本帧错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆