2011-08-12 4 views
8

크롬이 v14로 업데이트되었으므로 version three of the draft에서 version eight of the draft으로 변경되었습니다.WebSocket hybi 08+에서 데이터 프레임을 만드는 방법 (de)

WebSocket에서 내부 채팅 응용 프로그램을 실행하고 있는데 새로운 핸드 셰이크가 작동하더라도 데이터 프레임이 변경된 것 같습니다. 내 WebSocket 서버는 Nugget을 기반으로합니다.

초안 중 8 버전을 사용하는 WebSocket을 보유하고 있고 전선을 통해 전송되는 데이터의 프레임을 만드는 방법에 대한 예제가 있습니까?

답변

16

(How can I send and receive WebSocket messages on the server side?를 참조).

첫번째 바이트는 세 0 S가 지금까지 어떤 의미없는 비트가 예약되어, 거의 항상 1은 "최종 프레임"을 의미 1000 0001,이고 0001는 크롬이 ws.send() 방법 전송 텍스트 프레임 (것을 의미). .. 크롬 지금 또한 ArrayBuffer 이진 프레임을 보낼 수있는 텍스트와 이진 데이터 사이에 다를 수 있습니다 첫 번째 바이트의 마지막 4 비트, 0002 할 데이터의 디코딩이 정확히 작동 : 업데이트

(같은 방법으로)

두 번째 바이트는 프레임 크기를 나타내는 7 비트가 뒤에 오는 1 ("마스크 된"(인코딩 됨)을 의미)을 포함합니다. 000 0000111 1101 사이이면 그 크기입니다. 111 1110 인 경우 다음 2 바이트는 길이 (7 비트에 맞지 않으므로)이고, 111 1111이면 길이가 다음 바이트 (2 바이트가 맞지 않는 경우)입니다.

다음은 프레임 데이터를 디코딩해야하는 "마스크"인 4 바이트입니다. 이것은 indexOfByteInData mod 4으로 정의 된 마스크 중 하나를 사용하는 xor 인코딩을 사용하여 수행됩니다. 디코딩은 encodedByte xor maskByte (maskByteindexOfByteInData mod 4)과 같이 작동합니다.(

var length_code = bytes[1] & 127, // remove the first 1 by doing '& 127' 
    masks, 
    data; 

if(length_code === 126) { 
    masks = bytes.slice(4, 8); // 'slice' returns part of the byte array 
    data = bytes.slice(8);  // and accepts 'start' (inclusively) 
} else if(length_code === 127) { // and 'end' (exclusively) as arguments 
    masks = bytes.slice(10, 14); // Passing no 'end' makes 'end' the length 
    data = bytes.slice(14);  // of the array 
} else { 
    masks = bytes.slice(2, 6); 
    data = bytes.slice(6); 
} 

// 'map' replaces each element in the array as per a specified function 
// (each element will be replaced with what is returned by the function) 
// The passed function accepts the value and index of the element as its 
// arguments 
var decoded = data.map(function(byte, index) { // index === 0 for the first byte 
    return byte^masks[ index % 4 ];   // of 'data', not of 'bytes' 
    //   xor   mod 
}); 

또한 도움이 될 수 the specification을 다운로드 할 수 있습니다 : 이제

나는 모든 C#을 경험하고 있지 않다 말해야한다, 그러나 이것은 일부 의사 (일부 자바 스크립트 악센트 난 두려워)입니다 물론 형식을 이해하는 데 필요한 모든 것이 포함되어 있습니다.)

+0

달콤한 ... 나는 월요일에 직장에서 이것을 시도 할 것이다. 나는 그것이 작동한다면 받아 들여지는 대답을 줄 것이다 ... :) – gislikonrad

+0

마침내 내 websocket 서버에 대해이 솔루션을 살펴 보았다. 매력처럼 작동했습니다 ... 고마워, 남자 ... – gislikonrad

+0

@ Gísli Konráð : 좋아요. WebSocket은 실제로 디버깅에 익숙하지 않습니다. – pimvdb

2

Chrome의 정확도를 높이기 위해 Hixie-76 버전의 프로토콜을 HyBi-10 버전으로 변경했습니다. HyBi-08에서 HyBi-10까지는 모두 버전 8로보고됩니다. 실제로 와이어 형식이 아닌 사양 텍스트 일 ​​뿐이 기 때문입니다.

프레임 구성이 '\ x00 ... \ xff'에서 다른 것들 중에서 페이로드의 길이를 포함하는 각 프레임에 2-7 바이트 헤더를 사용하는 것으로 변경되었습니다. 사양의 section 4.2에는 프레임 형식의 다이어그램이 있습니다. 또한 클라이언트 (브라우저)에서 서버로의 데이터는 마스크 처리됩니다 (클라이언트 - 서버 프레임 헤더의 4 바이트는 마스크 해제 키를 포함합니다).

noVNC을 지원하기 위해 만든 웹 소켓 대 TCP 소켓 프록시/브리지 인 websockify을 볼 수 있습니다. 파이썬으로 구현되었지만 encode_hybidecode_hybi 루틴에서 아이디어를 얻을 수 있어야합니다. 그것은 매우 쉽게


하지만 형식을 이해하는 것이 중요합니다 :

8

이 C# 코드는 저에게 잘 작동합니다. 브라우저에서 제공되는 텍스트 데이터를 소켓을 통해 C# 서버로 디코딩합니다.

public static string GetDecodedData(byte[] buffer, int length) 
    { 
     byte b = buffer[1]; 
     int dataLength = 0; 
     int totalLength = 0; 
     int keyIndex = 0; 

     if (b - 128 <= 125) 
     { 
      dataLength = b - 128; 
      keyIndex = 2; 
      totalLength = dataLength + 6; 
     } 

     if (b - 128 == 126) 
     { 
      dataLength = BitConverter.ToInt16(new byte[] { buffer[3], buffer[2] }, 0); 
      keyIndex = 4; 
      totalLength = dataLength + 8; 
     } 

     if (b - 128 == 127) 
     { 
      dataLength = (int)BitConverter.ToInt64(new byte[] { buffer[9], buffer[8], buffer[7], buffer[6], buffer[5], buffer[4], buffer[3], buffer[2] }, 0); 
      keyIndex = 10; 
      totalLength = dataLength + 14; 
     } 

     if (totalLength > length) 
      throw new Exception("The buffer length is small than the data length"); 

     byte[] key = new byte[] { buffer[keyIndex], buffer[keyIndex + 1], buffer[keyIndex + 2], buffer[keyIndex + 3] }; 

     int dataIndex = keyIndex + 4; 
     int count = 0; 
     for (int i = dataIndex; i < totalLength; i++) 
     { 
      buffer[i] = (byte)(buffer[i]^key[count % 4]); 
      count++; 
     } 

     return Encoding.ASCII.GetString(buffer, dataIndex, dataLength); 
    } 
+0

질문에 따라 대답으로 표시되어야합니다 (C# 코드) – cdie

+0

'totalLength' 란 무엇이며 왜'keyIndex + 4'를 추가하나요? –

관련 문제