解码websocket帧

解码websocket帧,websocket,decoding,Websocket,Decoding,我正在尝试解码websocket帧,但在解码扩展有效负载时没有成功。以下是我迄今为止所取得的成就: char *in = data; char *buffer; unsigned int i; unsigned char mask[4]; unsigned int packet_length = 0; int rc; /* Expect a finished text frame. */ assert(in[0] == '\x81'); packet_length = ((unsigned c

我正在尝试解码websocket帧,但在解码扩展有效负载时没有成功。以下是我迄今为止所取得的成就:

char *in = data;
char *buffer;
unsigned int i;
unsigned char mask[4];
unsigned int packet_length = 0;
int rc;

/* Expect a finished text frame. */
assert(in[0] == '\x81');
packet_length = ((unsigned char) in[1]) & 0x7f;

mask[0] = in[2];
mask[1] = in[3];
mask[2] = in[4];
mask[3] = in[5];

if (packet_length <= 125) {           **// This decoding works**
     /* Unmask the payload. */
    for (i = 0; i < packet_length; i++)
        in[6 + i] ^= mask[i % 4];
    rc = asprintf(&buffer, "%.*s", packet_length, in + 6);
} else
    if (packet_length == 126) {       **//This decosing does NOT work**
        /* Unmask the payload. */
        for (i = 0; i < packet_length; i++)
          in[8 + i] ^= mask[i % 4];
        rc = asprintf(&buffer, "%.*s", packet_length, in + 8);
}
char*in=数据;
字符*缓冲区;
无符号整数i;
无符号字符掩码[4];
无符号整数包长度=0;
int rc;
/*希望有一个完整的文本框架*/
断言(在[0]='\x81');
数据包长度=((无符号字符)在[1])&0x7f;
掩码[0]=in[2];
掩码[1]=in[3];
掩码[2]=in[4];
掩码[3]=in[5];

if(packet_length如果packet_length为126,则以下2个字节给出要读取的数据长度。
如果数据包长度为127,则以下8个字节给出了要读取的数据长度。
掩码包含在以下4个字节中(在长度之后)。
要解码的消息如下所示

规范的第三部分对此进行了有益的说明

如果您将代码重新排序为

  • 读取数据包长度
  • 检查数据包长度是否为126或127。如果需要,请将数据包长度重新指定为以下2/4字节的值
  • 读取掩码(数据包长度后的4个字节,包括为上述步骤读取的任何额外2或8个字节)
  • 解码消息(掩码后的所有内容)

然后事情就应该开始了。

问题的症结在于>125字节的有效负载

格式非常简单,假设您使用JavaScript发送10个a:

ws.send("a".repeat(10))
ws.send("a".repeat(126))
然后服务器将接收:

bytes[16]=818a8258a610e339c771e339c771e339
bytes[134]=81fe007ee415f1e5857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574
  • 字节0:0x81只是接收到消息的指示器
  • 字节1:0x8a是长度,从中减去0x80,0x0A==10
  • 字节2、3、4、5:用于解密有效负载的4字节xor密钥
  • 其余的:有效载荷
但现在让我们假设您发送了126个JavaScript:

ws.send("a".repeat(10))
ws.send("a".repeat(126))
然后服务器将接收:

bytes[16]=818a8258a610e339c771e339c771e339
bytes[134]=81fe007ee415f1e5857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574
如果有效负载的长度大于125,字节1的值为0xfe,格式将更改为:

  • 字节0:0x81只是接收到消息的指示器
  • 字节1:将是0xfe
  • 字节2,3:作为uint16编号的有效负载长度
  • 字节4、5、6、7:用于解密有效负载的4字节异或密钥
  • 其余的:有效载荷
C#中的示例代码:

列出解码WebSocketFrame(字节[]字节)
{
List ret=新列表();
整数偏移=0;
而(偏移量+6<字节长度)
{
//格式:0==ascii/二进制1=length-0x80,字节2,3,4,5=key,6+len=message,用偏移量重复下一步。。。
int len=字节[offset+1]-0x80;

如果(len)做了一个小的修正:长度中的127表示以下8个字节包含有效负载长度(不是4),请不要使用十六进制进行算术!@Andrew为什么不?十六进制只是表示数字的一种方式。我使用它没有特别的问题,有时,特别是在协议解析中,它非常有用