Encoding 如何在服务器端发送和接收WebSocket消息?
如何根据协议使用WebSocket在服务器端发送和接收消息Encoding 如何在服务器端发送和接收WebSocket消息?,encoding,protocols,websocket,decoding,Encoding,Protocols,Websocket,Decoding,如何根据协议使用WebSocket在服务器端发送和接收消息 为什么当我从浏览器向服务器发送数据时,服务器上会出现看似随机的字节?数据是否以某种方式编码 框架在两个服务器中是如何工作的→ 客户与客户→ 服务器方向 注意:这是关于如何实现一个非常简单的服务器的一些解释和伪代码,该服务器可以按照最终的框架格式处理传入和传出的WebSocket消息。它不包括握手过程。此外,这一回答是出于教育目的;它不是一个功能齐全的实现 发送消息 (换句话说,服务器→ (浏览器) 您发送的帧需要根据WebSocke
发送消息 (换句话说,服务器→ (浏览器) 您发送的帧需要根据WebSocket帧格式进行格式化。对于发送消息,此格式如下所示:
decodedByte = encodedByte XOR masks[encodedByteIndex MOD 4]
- 包含数据类型的一个字节(以及一些超出普通服务器范围的附加信息)
- 包含长度的一个字节
- 如果长度与第二个字节不匹配,则为两个或八个字节(第二个字节是表示长度使用了多少字节的代码)
- 实际(原始)数据
1000 0001
(或129
)
第二个字节的第一位设置为0
,因为我们没有对数据进行编码(从服务器到客户端的编码不是强制性的)
有必要确定原始数据的长度,以便正确发送长度字节:
- 如果
0pimvdb的答案是用python实现的:
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; }
function encode($message) { $length = strlen($message); $bytesHeader = []; $bytesHeader[0] = 129; // 0x1 text frame (FIN + opcode) if ($length <= 125) { $bytesHeader[1] = $length; } else if ($length >= 126 && $length <= 65535) { $bytesHeader[1] = 126; $bytesHeader[2] = ( $length >> 8 ) & 255; $bytesHeader[3] = ( $length ) & 255; } else { $bytesHeader[1] = 127; $bytesHeader[2] = ( $length >> 56 ) & 255; $bytesHeader[3] = ( $length >> 48 ) & 255; $bytesHeader[4] = ( $length >> 40 ) & 255; $bytesHeader[5] = ( $length >> 32 ) & 255; $bytesHeader[6] = ( $length >> 24 ) & 255; $bytesHeader[7] = ( $length >> 16 ) & 255; $bytesHeader[8] = ( $length >> 8 ) & 255; $bytesHeader[9] = ( $length ) & 255; } $str = implode(array_map("chr", $bytesHeader)) . $message; return $str; }
Java实现(如果需要) 读取:客户端到服务器函数编码WebSocket(bytesRaw){ var bytesformated=新数组(); 字节格式化[0]=129; 如果(bytesRaw.length=126&&bytesRaw.length>8)&255; 字节格式化[3]=(bytesRaw.length)&255; }否则{ 字节格式化[1]=127; 字节格式化[2]=(bytesRaw.length>>56)&255; 字节格式化[3]=(bytesRaw.length>>48)&255; 字节格式化[4]=(bytesRaw.length>>40)&255; 字节格式化[5]=(bytesRaw.length>>32)&255; 字节格式化[6]=(bytesRaw.length>>24)&255; 字节格式化[7]=(bytesRaw.length>>16)&255; 字节格式化[8]=(bytesRaw.length>>8)&255; 字节格式化[9]=(bytesRaw.length)&255; } for(var i=0;i
int len = 0; byte[] b = new byte[buffLenth]; //rawIn is a Socket.getInputStream(); while(true){ len = rawIn.read(b); if(len!=-1){ byte rLength = 0; int rMaskIndex = 2; int rDataStart = 0; //b[0] is always text in my case so no need to check; byte data = b[1]; byte op = (byte) 127; rLength = (byte) (data & op); if(rLength==(byte)126) rMaskIndex=4; if(rLength==(byte)127) rMaskIndex=10; byte[] masks = new byte[4]; int j=0; int i=0; for(i=rMaskIndex;i<(rMaskIndex+4);i++){ masks[j] = b[i]; j++; } rDataStart = rMaskIndex + 4; int messLen = len - rDataStart; byte[] message = new byte[messLen]; for(i=rDataStart, j=0; i<len; i++, j++){ message[j] = (byte) (b[i] ^ masks[j % 4]); } parseMessage(new String(message)); //parseMessage(new String(b)); b = new byte[buffLenth]; } }
int len=0; 字节[]b=新字节[buffLenth]; //rawIn是一个Socket.getInputStream(); while(true){ len=rawIn.read(b); 如果(len!=-1){ 字节长度=0; int rMaskIndex=2; int rDataStart=0; //b[0]在我的情况下始终是文本,因此无需检查; 字节数据=b[1]; 字节op=(字节)127; rLength=(字节)(数据和操作); 如果(rLength==(字节)126)rMaskIndex=4; 如果(rLength==(byte)127)rMaskIndex=10; 字节[]掩码=新字节[4]; int j=0; int i=0; 对于(i=rMaskIndex;i>56)和(字节)255); 帧[3]=(字节)((len>>48)和(字节)255); 帧[4]=(字节)((len>>40)和(字节)255); 帧[5]=(字节)((len>>32)和(字节)255); 帧[6]=(字节)((len>>24)和(字节)255); 帧[7]=(字节)((len>>16)和(字节)255); 帧[8]=(字节)((len>>8)和(字节)255); 帧[9]=(字节)(len和(字节)255); 帧数=10; } int bLength=frameCount+rawData.length; 字节[]回复=新字节[bLength]; int-bLim=0; 对于(int i=0;i在Go中的实现 编码部件(服务器->浏览器)
Clojure,decode函数假定帧作为
的映射发送,因为实际大小可能与字节数组的大小不同,具体取决于输入流的块大小 此处张贴的代码:{:data byte array buffer:size int size of buffer}
(defn ws decode[帧] “解码websocket帧” (let[数据(:数据帧) dlen(位和(第二数据)127) mstart(如果(=dlen 127)10(如果(=dlen 126)4 2)) 遮罩(下降2(获取(+MSStart 4)数据)) msg(生成数组字节/类型(-:大小帧)(+mstart 4))] (循环[i(+mstart 4),j 0] (aset字节msg j(字节(位异或(第n个数据i)(第n个掩码(mod j 4 ')))) (如果(len 65535)10(如果(>len 125)4 2)) buf(生成数组字节/类型(+len blen)) _(aset字节buf 0-127);;(位或(未检查的字节0x80) (未选中的字节0x1) _(如果(=2 blen) (aset字节buf 1 len);;掩码0,len (做 (dorun(map#)(一组字节buf%1 (未检查字节(位和(位右移len(*(-2)8)) 255)))
fromclient = '\x81\x8c\xff\xb8\xbd\xbd\xb7\xdd\xd1\xd1\x90\x98\xea\xd2\x8d\xd4\xd9\x9c' # this looks like "?ŒOÇ¿¢gÓ ç\Ð=«ož" in unicode, received by server print DecodedCharArrayFromByteStreamIn(fromclient) # ['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!']
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; }
int len = 0; byte[] b = new byte[buffLenth]; //rawIn is a Socket.getInputStream(); while(true){ len = rawIn.read(b); if(len!=-1){ byte rLength = 0; int rMaskIndex = 2; int rDataStart = 0; //b[0] is always text in my case so no need to check; byte data = b[1]; byte op = (byte) 127; rLength = (byte) (data & op); if(rLength==(byte)126) rMaskIndex=4; if(rLength==(byte)127) rMaskIndex=10; byte[] masks = new byte[4]; int j=0; int i=0; for(i=rMaskIndex;i<(rMaskIndex+4);i++){ masks[j] = b[i]; j++; } rDataStart = rMaskIndex + 4; int messLen = len - rDataStart; byte[] message = new byte[messLen]; for(i=rDataStart, j=0; i<len; i++, j++){ message[j] = (byte) (b[i] ^ masks[j % 4]); } parseMessage(new String(message)); //parseMessage(new String(b)); b = new byte[buffLenth]; } }
public void brodcast(String mess) throws IOException{ 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){ frame[1] = (byte) 126; int len = rawData.length; frame[2] = (byte)((len >> 8 ) & (byte)255); frame[3] = (byte)(len & (byte)255); frameCount = 4; }else{ frame[1] = (byte) 127; int len = 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++; } out.write(reply); out.flush(); }
func encode (message string) (result []byte) { rawBytes := []byte(message) var idxData int length := byte(len(rawBytes)) if len(rawBytes) <= 125 { //one byte to store data length result = make([]byte, len(rawBytes) + 2) result[1] = length idxData = 2 } else if len(rawBytes) >= 126 && len(rawBytes) <= 65535 { //two bytes to store data length result = make([]byte, len(rawBytes) + 4) result[1] = 126 //extra storage needed result[2] = ( length >> 8 ) & 255 result[3] = ( length ) & 255 idxData = 4 } else { result = make([]byte, len(rawBytes) + 10) result[1] = 127 result[2] = ( length >> 56 ) & 255 result[3] = ( length >> 48 ) & 255 result[4] = ( length >> 40 ) & 255 result[5] = ( length >> 32 ) & 255 result[6] = ( length >> 24 ) & 255 result[7] = ( length >> 16 ) & 255 result[8] = ( length >> 8 ) & 255 result[9] = ( length ) & 255 idxData = 10 } result[0] = 129 //only text is supported // put raw data at the correct index for i, b := range rawBytes { result[idxData + i] = b } return }
func decode (rawBytes []byte) string { var idxMask int if rawBytes[1] == 126 { idxMask = 4 } else if rawBytes[1] == 127 { idxMask = 10 } else { idxMask = 2 } masks := rawBytes[idxMask:idxMask + 4] data := rawBytes[idxMask + 4:len(rawBytes)] decoded := make([]byte, len(rawBytes) - idxMask + 4) for i, b := range data { decoded[i] = b ^ masks[i % 4] } return string(decoded) }
(defn ws-decode [frame] "decodes websocket frame" (let [data (:data frame) dlen (bit-and (second data) 127) mstart (if (== dlen 127) 10 (if (== dlen 126) 4 2)) mask (drop 2 (take (+ mstart 4) data)) msg (make-array Byte/TYPE (- (:size frame) (+ mstart 4)))] (loop [i (+ mstart 4), j 0] (aset-byte msg j (byte (bit-xor (nth data i) (nth mask (mod j 4))))) (if (< i (dec(:size frame))) (recur (inc i) (inc j)))) msg)) (defn ws-encode [data] "takes in bytes, return websocket frame" (let [len (count data) blen (if (> len 65535) 10 (if (> len 125) 4 2)) buf (make-array Byte/TYPE (+ len blen)) _ (aset-byte buf 0 -127) ;;(bit-or (unchecked-byte 0x80) (unchecked-byte 0x1) _ (if (= 2 blen) (aset-byte buf 1 len) ;;mask 0, len (do (dorun(map #(aset-byte buf %1 (unchecked-byte (bit-and (bit-shift-right len (*(- %2 2) 8)) 255))) (range 2 blen) (into ()(range 2 blen)))) (aset-byte buf 1 (if (> blen 4) 127 126)))) _ (System/arraycopy data 0 buf blen len)] buf))
function encode($message) { $length = strlen($message); $bytesHeader = []; $bytesHeader[0] = 129; // 0x1 text frame (FIN + opcode) if ($length <= 125) { $bytesHeader[1] = $length; } else if ($length >= 126 && $length <= 65535) { $bytesHeader[1] = 126; $bytesHeader[2] = ( $length >> 8 ) & 255; $bytesHeader[3] = ( $length ) & 255; } else { $bytesHeader[1] = 127; $bytesHeader[2] = ( $length >> 56 ) & 255; $bytesHeader[3] = ( $length >> 48 ) & 255; $bytesHeader[4] = ( $length >> 40 ) & 255; $bytesHeader[5] = ( $length >> 32 ) & 255; $bytesHeader[6] = ( $length >> 24 ) & 255; $bytesHeader[7] = ( $length >> 16 ) & 255; $bytesHeader[8] = ( $length >> 8 ) & 255; $bytesHeader[9] = ( $length ) & 255; } $str = implode(array_map("chr", $bytesHeader)) . $message; return $str; }
private String DecodeMessage(Byte[] bytes) { String incomingData = String.Empty; Byte secondByte = bytes[1]; Int32 dataLength = secondByte & 127; Int32 indexFirstMask = 2; if (dataLength == 126) indexFirstMask = 4; else if (dataLength == 127) indexFirstMask = 10; IEnumerable<Byte> keys = bytes.Skip(indexFirstMask).Take(4); Int32 indexFirstDataByte = indexFirstMask + 4; Byte[] decoded = new Byte[bytes.Length - indexFirstDataByte]; for (Int32 i = indexFirstDataByte, j = 0; i < bytes.Length; i++, j++) { decoded[j] = (Byte)(bytes[i] ^ keys.ElementAt(j % 4)); } return incomingData = Encoding.UTF8.GetString(decoded, 0, decoded.Length); }
private static Byte[] EncodeMessageToSend(String message) { Byte[] response; Byte[] bytesRaw = Encoding.UTF8.GetBytes(message); Byte[] frame = new Byte[10]; Int32 indexStartRawData = -1; Int32 length = bytesRaw.Length; frame[0] = (Byte)129; if (length <= 125) { frame[1] = (Byte)length; indexStartRawData = 2; } else if (length >= 126 && length <= 65535) { frame[1] = (Byte)126; frame[2] = (Byte)((length >> 8) & 255); frame[3] = (Byte)(length & 255); indexStartRawData = 4; } else { frame[1] = (Byte)127; frame[2] = (Byte)((length >> 56) & 255); frame[3] = (Byte)((length >> 48) & 255); frame[4] = (Byte)((length >> 40) & 255); frame[5] = (Byte)((length >> 32) & 255); frame[6] = (Byte)((length >> 24) & 255); frame[7] = (Byte)((length >> 16) & 255); frame[8] = (Byte)((length >> 8) & 255); frame[9] = (Byte)(length & 255); indexStartRawData = 10; } response = new Byte[indexStartRawData + length]; Int32 i, reponseIdx = 0; //Add the frame bytes to the reponse for (i = 0; i < indexStartRawData; i++) { response[reponseIdx] = frame[i]; reponseIdx++; } //Add the data bytes to the response for (i = 0; i < length; i++) { response[reponseIdx] = bytesRaw[i]; reponseIdx++; } return response; }
function Decode($M){ $M = array_map("ord", str_split($M)); $L = $M[1] AND 127; if ($L == 126) $iFM = 4; else if ($L == 127) $iFM = 10; else $iFM = 2; $Masks = array_slice($M, $iFM, 4); $Out = ""; for ($i = $iFM + 4, $j = 0; $i < count($M); $i++, $j++ ) { $Out .= chr($M[$i] ^ $Masks[$j % 4]); } return $Out; }
def DecodedWebsockRecieve(stringStreamIn): byteArray = stringStreamIn datalength = byteArray[1] & 127 indexFirstMask = 2 if datalength == 126: indexFirstMask = 4 elif datalength == 127: indexFirstMask = 10 masks = [m for m in byteArray[indexFirstMask : indexFirstMask+4]] indexFirstDataByte = indexFirstMask + 4 decodedChars = [] i = indexFirstDataByte j = 0 while i < len(byteArray): decodedChars.append( chr(byteArray[i] ^ masks[j % 4]) ) i += 1 j += 1 return ''.join(decodedChars) def EncodeWebSockSend(socket,data): bytesFormatted = [] bytesFormatted.append(129) bytesRaw = data.encode() bytesLength = len(bytesRaw) if bytesLength <= 125 : bytesFormatted.append(bytesLength) elif bytesLength >= 126 and bytesLength <= 65535 : bytesFormatted.append(126) bytesFormatted.append( ( bytesLength >> 8 ) & 255 ) bytesFormatted.append( bytesLength & 255 ) else : bytesFormatted.append( 127 ) bytesFormatted.append( ( bytesLength >> 56 ) & 255 ) bytesFormatted.append( ( bytesLength >> 48 ) & 255 ) bytesFormatted.append( ( bytesLength >> 40 ) & 255 ) bytesFormatted.append( ( bytesLength >> 32 ) & 255 ) bytesFormatted.append( ( bytesLength >> 24 ) & 255 ) bytesFormatted.append( ( bytesLength >> 16 ) & 255 ) bytesFormatted.append( ( bytesLength >> 8 ) & 255 ) bytesFormatted.append( bytesLength & 255 ) bytesFormatted = bytes(bytesFormatted) bytesFormatted = bytesFormatted + bytesRaw socket.send(bytesFormatted)
bufSize = 1024 read = DecodedWebsockRecieve(socket.recv(bufSize))
EncodeWebSockSend(sock,"hellooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo")