当前位置: 首页 > 知识库问答 >
问题:

Java Websocket文本帧错误,长度>=128?

陶飞鸿
2023-03-14

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

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

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

服务器显示正在接收完整消息,并尝试在没有运行时错误或错误的情况下完整广播消息。正如我的系统所示,它也将发送到16位长度的创建者。出来println()。服务器上的我的java控制台读取:

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

我目前正在写一个帧测试器来测试我用广播发送的帧,但希望社区能够为我节省一些腿部工作。真正奇怪的是126和127有效载荷长度的工作和反映使用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个答案

钱弘壮
2023-03-14

几点注意事项。

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

这里有一个简单的例子。

下面的代码是根据:EclipsePublicLicense 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));
        }
    }
}
 类似资料:
  • 问题内容: 包裹。他们为什么不能更轻松?我正在尝试编写一个将ArrayList作为包裹发送的应用程序。当我尝试在第二个活动中获取Intent时,将收到错误消息: 我已经尝试过使用Strings而不是Parcelable arraylist,这将起作用。即使我在设置项目后得到ArrayList,它也将起作用: 但是,由于我想在第二个活动中获取arraylist,因此出现了先前的错误: 可能是什么错误

  • 问题内容: 继承人错误: 这是导致它的代码: 图标是文件数组。奇怪的是,我的计算机可以在任何图像查看器中正常读取图像。谷歌搜索错误没有给我任何结果。我有很多图像需要阅读,因此除了将图像转换为BufferedImage之外,它们是获取图像尺寸的一种替代方法吗?这样可以解决问题吗?有没有办法修复这些图像?我是通过从iOS设备收集应用程序图标来获得它们的。使用我自己的设备进行的测试没有产生任何错误,尽管

  • 我正在尝试合并两个MP3文件到一个单一的MP3文件。文件保存在SD卡中,但无法播放。首先,我将MP3转换成存储在文件夹中的WAV文件,并输出到SD卡上。它还给出了。

  • 这个错误开始突然出现,当我登录到我的应用程序(通过firebase)时,它必须显示一个列表,然而,当登录时,它没有显示任何东西,并且这个错误开始在日志中出现几次 日志: 我看不到这个错误来自什么activity或片段,我只知道当我之后登录到我的列表时,它在列表中没有显示任何东西并且这些错误在日志中以一行的形式出现

  • 我忘了把我的更改推进到一个我已经工作了几个月的项目中。这导致了一个非常大的. git目录(约11 GB)。回购中的其余文件组合起来要比这少得多。我想把所有的提交都推到github上,如果不是一次完成,那就增量完成。因此,我试图一个接一个地推动提交,以便保持在每次推送的限制之下。 我的第一次提交(~5.5 GB)推送失败,并给出错误。 我在谷歌搜索时发现了一些类似的信息,但它们都指向一个特定的字符错

  • 大家好,我正在构建一个聊天服务器,我在屏幕上使用一个文本字段来键入用户写的聊天消息,这个想法是,当他键入消息时,它就像一个泡泡在一个人的头上一样工作。 我的问题是,为了不使文本框太大或太小,有没有一种方法可以使文本框调整大小(如果你愿意,可以修剪),以便它调整到文本字段中所写的文本? 附言。我使用JavaFx scenebuilder来完成所有这些。