亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在服務器端發送和接收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 關注
  • 3077 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號