为了账号安全,请及时绑定邮箱和手机立即绑定

如何在服务器端发送和接收WebSocket消息?

如何在服务器端发送和接收WebSocket消息?

呼如林 2019-07-01 16:25:34
如何在服务器端发送和接收WebSocket消息?如何按照协议使用WebSocket在服务器端发送和接收消息?为什么当我从浏览器向服务器发送数据时,在服务器上得到看似随机的字节?它是以某种方式编码的数据吗?在服务器→客户端和客户端→服务器方向中,框架是如何工作的?
查看完整描述

3 回答

?
一只名叫tom的猫

TA贡献1906条经验 获得超3个赞

JavaScript实现:

function encodeWebSocket(bytesRaw){
    var bytesFormatted = new Array();
    bytesFormatted[0] = 129;
    if (bytesRaw.length <= 125) {
        bytesFormatted[1] = bytesRaw.length;
    } else if (bytesRaw.length >= 126 && bytesRaw.length <= 65535) {
        bytesFormatted[1] = 126;
        bytesFormatted[2] = ( bytesRaw.length >> 8 ) & 255;
        bytesFormatted[3] = ( bytesRaw.length      ) & 255;
    } else {
        bytesFormatted[1] = 127;
        bytesFormatted[2] = ( bytesRaw.length >> 56 ) & 255;
        bytesFormatted[3] = ( bytesRaw.length >> 48 ) & 255;
        bytesFormatted[4] = ( bytesRaw.length >> 40 ) & 255;
        bytesFormatted[5] = ( bytesRaw.length >> 32 ) & 255;
        bytesFormatted[6] = ( bytesRaw.length >> 24 ) & 255;
        bytesFormatted[7] = ( bytesRaw.length >> 16 ) & 255;
        bytesFormatted[8] = ( bytesRaw.length >>  8 ) & 255;
        bytesFormatted[9] = ( bytesRaw.length       ) & 255;
    }
    for (var i = 0; i < bytesRaw.length; i++){
        bytesFormatted.push(bytesRaw.charCodeAt(i));
    }
    return bytesFormatted;
}

function decodeWebSocket (data){
    var datalength = data[1] & 127;
    var indexFirstMask = 2;
    if (datalength == 126) {
        indexFirstMask = 4;
    } else if (datalength == 127) {
        indexFirstMask = 10;
    }
    var masks = data.slice(indexFirstMask,indexFirstMask + 4);
    var i = indexFirstMask + 4;
    var index = 0;
    var output = "";
    while (i < data.length) {
        output += String.fromCharCode(data[i++] ^ masks[index++ % 4]);
    }
    return output;
}


查看完整回答
反对 回复 2019-07-01
?
慕森卡

TA贡献1806条经验 获得超8个赞

发送消息

(换句话说,服务器→浏览器)

您要发送的帧需要根据WebSocket框架格式进行格式化。对于发送消息,此格式如下:

  • 包含数据类型的一个字节(以及一些超出普通服务器范围的附加信息)
  • 包含长度的字节
  • 如果长度不适合于第二个字节,则为两个或八个字节(然后,第二个字节是表示长度使用多少字节的代码)。
  • 实际(原始)数据

第一个字节是1000 0001(或129)用于文本帧。

第二个字节的第一个位设置为0因为我们没有对数据进行编码(从服务器到客户端的编码不是强制性的)。

有必要确定原始数据的长度,以便正确地发送长度字节:

  • 如果

    0 <= length <= 125

    ,您不需要额外的字节
  • 如果

    126 <= length <= 65535

    ,您需要另外两个字节,第二个字节是

    126

  • 如果

    length >= 65536

    ,您需要额外的8个字节,第二个字节是

    127

长度必须被分割成单独的字节,这意味着您需要将位移到右边(数量为8位),然后只保留最后的8位。AND 1111 1111(这是255).

在长度字节之后是原始数据。

这将导致以下伪代码:

bytesFormatted[0] = 129

indexStartRawData = -1 // it doesn't matter what value is
                       // set here - it will be set now:

if bytesRaw.length <= 125
    bytesFormatted[1] = bytesRaw.length

    indexStartRawData = 2

else if bytesRaw.length >= 126 and bytesRaw.length <= 65535
    bytesFormatted[1] = 126
    bytesFormatted[2] = ( bytesRaw.length >> 8 ) AND 255
    bytesFormatted[3] = ( bytesRaw.length      ) AND 255

    indexStartRawData = 4

else
    bytesFormatted[1] = 127
    bytesFormatted[2] = ( bytesRaw.length >> 56 ) AND 255
    bytesFormatted[3] = ( bytesRaw.length >> 48 ) AND 255
    bytesFormatted[4] = ( bytesRaw.length >> 40 ) AND 255
    bytesFormatted[5] = ( bytesRaw.length >> 32 ) AND 255
    bytesFormatted[6] = ( bytesRaw.length >> 24 ) AND 255
    bytesFormatted[7] = ( bytesRaw.length >> 16 ) AND 255
    bytesFormatted[8] = ( bytesRaw.length >>  8 ) AND 255
    bytesFormatted[9] = ( bytesRaw.length       ) AND 255

    indexStartRawData = 10

// put raw data at the correct index
bytesFormatted.put(bytesRaw, indexStartRawData)


// now send bytesFormatted (e.g. write it to the socket stream)

接收讯息

(换句话说,浏览器→服务器)

您获得的帧格式如下:

  • 包含数据类型的一个字节。
  • 包含长度的字节
  • 如果长度不适合第二个字节,则增加两个或八个字节。
  • 四个字节,它们是掩码(=解码键)
  • 实际数据

第一个字节通常并不重要-如果您只是发送文本,则只使用文本类型。它将是1000 0001(或129)在这种情况下。

第二个字节和额外的两个或八个字节需要一些解析,因为您需要知道长度使用了多少字节(您需要知道实际数据的起始位置)。长度本身通常是不必要的,因为您已经有了数据。

第二个字节的第一个位总是1这意味着数据被蒙住了(=编码)。从客户端到服务器的消息总是被屏蔽。你需要删除第一位secondByte AND 0111 1111..有两种情况下,结果字节不表示长度,因为它不适合于第二个字节:

  • 第二个字节

    0111 1110

    ,或

    126

    ,表示长度使用以下两个字节
  • 第二个字节

    0111 1111

    ,或

    127

    ,表示长度使用以下八个字节

这四个掩码字节用于解码已发送的实际数据。解码算法如下:

decodedByte = encodedByte XOR masks[encodedByteIndex MOD 4]

哪里encodedByte是数据中的原始字节,encodedByteIndex是从第一个字节计数的字节的索引(偏移)。真实数据,其中有索引0masks包含四个掩码字节的数组。

这导致了用于解码的下列伪码:

secondByte = bytes[1]

length = secondByte AND 127 // may not be the actual length in the two special cases

indexFirstMask = 2          // if not a special case

if length == 126            // if a special case, change indexFirstMask
    indexFirstMask = 4

else if length == 127       // ditto
    indexFirstMask = 10

masks = bytes.slice(indexFirstMask, 4) // four bytes starting from indexFirstMask

indexFirstDataByte = indexFirstMask + 4 // four bytes further

decoded = new array

decoded.length = bytes.length - indexFirstDataByte // length of real data

for i = indexFirstDataByte, j = 0; i < bytes.length; i++, j++
    decoded[j] = bytes[i] XOR masks[j MOD 4]


// now use "decoded" to interpret the received data


查看完整回答
反对 回复 2019-07-01
  • 3 回答
  • 0 关注
  • 3021 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信