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

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

  • 如何按照协议使用WebSocket在服务器端发送和接收消息?

  • 为什么当我从浏览器向服务器发送数据时,在服务器上得到看似随机的字节?它是以某种方式编码的数据吗?

  • 在服务器→客户端和客户端→服务器方向中,框架是如何工作的?


呼如林
浏览 3031回答 3
3回答

一只名叫tom的猫

JavaScript实现:function&nbsp;encodeWebSocket(bytesRaw){ &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;bytesFormatted&nbsp;=&nbsp;new&nbsp;Array(); &nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[0]&nbsp;=&nbsp;129; &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(bytesRaw.length&nbsp;<=&nbsp;125)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[1]&nbsp;=&nbsp;bytesRaw.length; &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;if&nbsp;(bytesRaw.length&nbsp;>=&nbsp;126&nbsp;&&&nbsp;bytesRaw.length&nbsp;<=&nbsp;65535)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[1]&nbsp;=&nbsp;126; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[2]&nbsp;=&nbsp;(&nbsp;bytesRaw.length&nbsp;>>&nbsp;8&nbsp;)&nbsp;&&nbsp;255; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[3]&nbsp;=&nbsp;(&nbsp;bytesRaw.length&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;&&nbsp;255; &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[1]&nbsp;=&nbsp;127; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[2]&nbsp;=&nbsp;(&nbsp;bytesRaw.length&nbsp;>>&nbsp;56&nbsp;)&nbsp;&&nbsp;255; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[3]&nbsp;=&nbsp;(&nbsp;bytesRaw.length&nbsp;>>&nbsp;48&nbsp;)&nbsp;&&nbsp;255; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[4]&nbsp;=&nbsp;(&nbsp;bytesRaw.length&nbsp;>>&nbsp;40&nbsp;)&nbsp;&&nbsp;255; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[5]&nbsp;=&nbsp;(&nbsp;bytesRaw.length&nbsp;>>&nbsp;32&nbsp;)&nbsp;&&nbsp;255; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[6]&nbsp;=&nbsp;(&nbsp;bytesRaw.length&nbsp;>>&nbsp;24&nbsp;)&nbsp;&&nbsp;255; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[7]&nbsp;=&nbsp;(&nbsp;bytesRaw.length&nbsp;>>&nbsp;16&nbsp;)&nbsp;&&nbsp;255; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[8]&nbsp;=&nbsp;(&nbsp;bytesRaw.length&nbsp;>>&nbsp;&nbsp;8&nbsp;)&nbsp;&&nbsp;255; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[9]&nbsp;=&nbsp;(&nbsp;bytesRaw.length&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;&&nbsp;255; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(var&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;<&nbsp;bytesRaw.length;&nbsp;i++){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted.push(bytesRaw.charCodeAt(i)); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;bytesFormatted; } function&nbsp;decodeWebSocket&nbsp;(data){ &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;datalength&nbsp;=&nbsp;data[1]&nbsp;&&nbsp;127; &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;indexFirstMask&nbsp;=&nbsp;2; &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(datalength&nbsp;==&nbsp;126)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;indexFirstMask&nbsp;=&nbsp;4; &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;if&nbsp;(datalength&nbsp;==&nbsp;127)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;indexFirstMask&nbsp;=&nbsp;10; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;masks&nbsp;=&nbsp;data.slice(indexFirstMask,indexFirstMask&nbsp;+&nbsp;4); &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;i&nbsp;=&nbsp;indexFirstMask&nbsp;+&nbsp;4; &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;index&nbsp;=&nbsp;0; &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;output&nbsp;=&nbsp;""; &nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(i&nbsp;<&nbsp;data.length)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;output&nbsp;+=&nbsp;String.fromCharCode(data[i++]&nbsp;^&nbsp;masks[index++&nbsp;%&nbsp;4]); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;output; }

慕森卡

发送消息(换句话说,服务器→浏览器)您要发送的帧需要根据WebSocket框架格式进行格式化。对于发送消息,此格式如下:包含数据类型的一个字节(以及一些超出普通服务器范围的附加信息)包含长度的字节如果长度不适合于第二个字节,则为两个或八个字节(然后,第二个字节是表示长度使用多少字节的代码)。实际(原始)数据第一个字节是1000 0001(或129)用于文本帧。第二个字节的第一个位设置为0因为我们没有对数据进行编码(从服务器到客户端的编码不是强制性的)。有必要确定原始数据的长度,以便正确地发送长度字节:如果0 <= length <= 125,您不需要额外的字节如果126 <= length <= 65535,您需要另外两个字节,第二个字节是126如果length >= 65536,您需要额外的8个字节,第二个字节是127长度必须被分割成单独的字节,这意味着您需要将位移到右边(数量为8位),然后只保留最后的8位。AND 1111 1111(这是255).在长度字节之后是原始数据。这将导致以下伪代码:bytesFormatted[0]&nbsp;=&nbsp;129 indexStartRawData&nbsp;=&nbsp;-1&nbsp;//&nbsp;it&nbsp;doesn't&nbsp;matter&nbsp;what&nbsp;value&nbsp;is &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;set&nbsp;here&nbsp;-&nbsp;it&nbsp;will&nbsp;be&nbsp;set&nbsp;now: if&nbsp;bytesRaw.length&nbsp;<=&nbsp;125 &nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[1]&nbsp;=&nbsp;bytesRaw.length &nbsp;&nbsp;&nbsp;&nbsp;indexStartRawData&nbsp;=&nbsp;2 else&nbsp;if&nbsp;bytesRaw.length&nbsp;>=&nbsp;126&nbsp;and&nbsp;bytesRaw.length&nbsp;<=&nbsp;65535 &nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[1]&nbsp;=&nbsp;126 &nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[2]&nbsp;=&nbsp;(&nbsp;bytesRaw.length&nbsp;>>&nbsp;8&nbsp;)&nbsp;AND&nbsp;255 &nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[3]&nbsp;=&nbsp;(&nbsp;bytesRaw.length&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;AND&nbsp;255 &nbsp;&nbsp;&nbsp;&nbsp;indexStartRawData&nbsp;=&nbsp;4 else &nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[1]&nbsp;=&nbsp;127 &nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[2]&nbsp;=&nbsp;(&nbsp;bytesRaw.length&nbsp;>>&nbsp;56&nbsp;)&nbsp;AND&nbsp;255 &nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[3]&nbsp;=&nbsp;(&nbsp;bytesRaw.length&nbsp;>>&nbsp;48&nbsp;)&nbsp;AND&nbsp;255 &nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[4]&nbsp;=&nbsp;(&nbsp;bytesRaw.length&nbsp;>>&nbsp;40&nbsp;)&nbsp;AND&nbsp;255 &nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[5]&nbsp;=&nbsp;(&nbsp;bytesRaw.length&nbsp;>>&nbsp;32&nbsp;)&nbsp;AND&nbsp;255 &nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[6]&nbsp;=&nbsp;(&nbsp;bytesRaw.length&nbsp;>>&nbsp;24&nbsp;)&nbsp;AND&nbsp;255 &nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[7]&nbsp;=&nbsp;(&nbsp;bytesRaw.length&nbsp;>>&nbsp;16&nbsp;)&nbsp;AND&nbsp;255 &nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[8]&nbsp;=&nbsp;(&nbsp;bytesRaw.length&nbsp;>>&nbsp;&nbsp;8&nbsp;)&nbsp;AND&nbsp;255 &nbsp;&nbsp;&nbsp;&nbsp;bytesFormatted[9]&nbsp;=&nbsp;(&nbsp;bytesRaw.length&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;AND&nbsp;255 &nbsp;&nbsp;&nbsp;&nbsp;indexStartRawData&nbsp;=&nbsp;10 //&nbsp;put&nbsp;raw&nbsp;data&nbsp;at&nbsp;the&nbsp;correct&nbsp;index bytesFormatted.put(bytesRaw,&nbsp;indexStartRawData) //&nbsp;now&nbsp;send&nbsp;bytesFormatted&nbsp;(e.g.&nbsp;write&nbsp;it&nbsp;to&nbsp;the&nbsp;socket&nbsp;stream)接收讯息(换句话说,浏览器→服务器)您获得的帧格式如下:包含数据类型的一个字节。包含长度的字节如果长度不适合第二个字节,则增加两个或八个字节。四个字节,它们是掩码(=解码键)实际数据第一个字节通常并不重要-如果您只是发送文本,则只使用文本类型。它将是1000 0001(或129)在这种情况下。第二个字节和额外的两个或八个字节需要一些解析,因为您需要知道长度使用了多少字节(您需要知道实际数据的起始位置)。长度本身通常是不必要的,因为您已经有了数据。第二个字节的第一个位总是1这意味着数据被蒙住了(=编码)。从客户端到服务器的消息总是被屏蔽。你需要删除第一位secondByte AND 0111 1111..有两种情况下,结果字节不表示长度,因为它不适合于第二个字节:第二个字节0111 1110,或126,表示长度使用以下两个字节第二个字节0111 1111,或127,表示长度使用以下八个字节这四个掩码字节用于解码已发送的实际数据。解码算法如下:decodedByte&nbsp;=&nbsp;encodedByte&nbsp;XOR&nbsp;masks[encodedByteIndex&nbsp;MOD&nbsp;4]哪里encodedByte是数据中的原始字节,encodedByteIndex是从第一个字节计数的字节的索引(偏移)。真实数据,其中有索引0.&nbsp;masks包含四个掩码字节的数组。这导致了用于解码的下列伪码:secondByte&nbsp;=&nbsp;bytes[1] length&nbsp;=&nbsp;secondByte&nbsp;AND&nbsp;127&nbsp;//&nbsp;may&nbsp;not&nbsp;be&nbsp;the&nbsp;actual&nbsp;length&nbsp;in&nbsp;the&nbsp;two&nbsp;special&nbsp;cases indexFirstMask&nbsp;=&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;if&nbsp;not&nbsp;a&nbsp;special&nbsp;case if&nbsp;length&nbsp;==&nbsp;126&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;if&nbsp;a&nbsp;special&nbsp;case,&nbsp;change&nbsp;indexFirstMask &nbsp;&nbsp;&nbsp;&nbsp;indexFirstMask&nbsp;=&nbsp;4 else&nbsp;if&nbsp;length&nbsp;==&nbsp;127&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;ditto &nbsp;&nbsp;&nbsp;&nbsp;indexFirstMask&nbsp;=&nbsp;10 masks&nbsp;=&nbsp;bytes.slice(indexFirstMask,&nbsp;4)&nbsp;//&nbsp;four&nbsp;bytes&nbsp;starting&nbsp;from&nbsp;indexFirstMask indexFirstDataByte&nbsp;=&nbsp;indexFirstMask&nbsp;+&nbsp;4&nbsp;//&nbsp;four&nbsp;bytes&nbsp;further decoded&nbsp;=&nbsp;new&nbsp;array decoded.length&nbsp;=&nbsp;bytes.length&nbsp;-&nbsp;indexFirstDataByte&nbsp;//&nbsp;length&nbsp;of&nbsp;real&nbsp;data for&nbsp;i&nbsp;=&nbsp;indexFirstDataByte,&nbsp;j&nbsp;=&nbsp;0;&nbsp;i&nbsp;<&nbsp;bytes.length;&nbsp;i++,&nbsp;j++ &nbsp;&nbsp;&nbsp;&nbsp;decoded[j]&nbsp;=&nbsp;bytes[i]&nbsp;XOR&nbsp;masks[j&nbsp;MOD&nbsp;4] //&nbsp;now&nbsp;use&nbsp;"decoded"&nbsp;to&nbsp;interpret&nbsp;the&nbsp;received&nbsp;data
打开App,查看更多内容
随时随地看视频慕课网APP