2014-11-19 5 views
1

저는 C# Web Socket 서버에서 약 24 시간 동안 작업했습니다.C# - Websocket - 클라이언트에게 메시지 보내기

현재 핸드 셰이크를 완료하고 연결을 초기화하는 방법을 알아 냈습니다.

또한 byte[] 데이터를 가져 와서 원래의 문자열로 디코딩하는 방법을 알아 냈습니다.

하지만 지금은 붙어있어 도움을 찾고 있습니다.

올바른 데이터 구조를 조합하여 클라이언트에 다시 보내는 방법을 알아낼 수 없습니다. 받은 원본 데이터를 보내면 클라이언트 측 웹 소켓 을 마스크 처리 할 수 ​​없다는 메시지가 나타납니다 (이것이 디코딩되어야하는 이유입니다).

그래서 기본적으로 WebSocket 클라이언트로 응답 데이터를 보내려면 어떻게 구성해야합니까?

저는 연구를 위해 http://tools.ietf.org/html/rfc6455을 리소스로 사용했습니다.

여기에 일반 소켓 만 사용하고 있습니다.

https://developer.mozilla.org/en-US/docs/WebSockets/Writing_WebSocket_servers

https://developer.mozilla.org/en-US/docs/WebSockets/Writing_WebSocket_server

그들이 모두처럼 보인다 :

if (dataBuffer.Length > 0) 
{ 
    if (dataBuffer[0] == 129) 
    { 
     int msg_length = dataBuffer[1] - 128; 
     if (msg_length <= 125) 
     { 
      // Msg ready to decode. 
      Log.info("Message Length: " + msg_length); 


      Byte[] decoded = new Byte[dataBuffer.Length]; 
      Byte[] encoded = new Byte[dataBuffer.Length - 6]; 

      Array.Copy(dataBuffer, 6, encoded, 0, msg_length); 

      Byte[] key = new Byte[4] { dataBuffer[2], dataBuffer[3], dataBuffer[4], dataBuffer[5] }; 
      for (int i = 0; i < encoded.Length; i++) 
      { 
       decoded[i] = (Byte)(encoded[i]^key[i % 4]); 
      } 

      Log.info("MSG: " + Encoding.UTF8.GetString(decoded)); 

      byte[] return_msg = new byte[decoded.Length + 8]; 

      return_msg[0] = 1; 
      return_msg[1] = 0; 
      return_msg[2] = 0; 
      return_msg[3] = 0; 
      // OP Code 
      return_msg[4] = 0x1; 
      return_msg[5] = 0x0; 
      return_msg[6] = 0x0; 
      return_msg[7] = 0x0; 

      Array.Copy(decoded, 0, return_msg, 8, decoded.Length); 

      socket.Send(return_msg); 
     } 
     else if (msg_length == 126) 
     { 
      // Longer Message 
      msg_length = dataBuffer[2] + dataBuffer[3]; 

      Log.info("Message Length: " + msg_length); 

      Byte[] key = new Byte[4] { dataBuffer[4], dataBuffer[5], dataBuffer[6], dataBuffer[7] }; 

      Byte[] decoded = new Byte[dataBuffer.Length]; 
      Byte[] encoded = new Byte[dataBuffer.Length - 8]; 

      Array.Copy(dataBuffer, 8, encoded, 0, msg_length); 

      for (int i = 0; i < encoded.Length; i++) 
      { 
       decoded[i] = (Byte)(encoded[i]^key[i % 4]); 
      } 

      Log.info("MSG: " + Encoding.UTF8.GetString(decoded)); 
      byte[] return_msg = new byte[decoded.Length + 4]; 

      return_msg[0] = 129; 
      return_msg[1] = 0; 
      return_msg[2] = 0; 
      return_msg[3] = 0; 

      Array.Copy(decoded,0,return_msg,4,decoded.Length); 

      socket.Send(return_msg); 
     } 
     else if (msg_length == 127) 
     { 
      // Huge Message: 
      Log.info("BIG MESSAGE"); 
     } 
    } 

} 
+0

재미있는 일이나 직업을 배우고 있습니까? 후자의 경우 TcpClient를 체크 아웃 했습니까? 그것은 당신을 위해 많은 일을합니다. –

+1

나는 그것을 수동으로하는 것이 더 나은 학습 경험이라고 생각했다. –

답변

2

쓰고 C#을 웹 소켓 서버에 대한이 두 기사를보세요 : 여기

내 디코딩 코드 동일한 기사, 그러나 그들은이지 않는다! 첫 번째 링크의 this part에는 프레임을 만드는 방법에 대한 설명이 있습니다. FIN

  • :

    UPDATE

    첫번째 바이트는 여러 가지 정보를 포함하는 프레임은 전체 메시지를 포함한다는 것을 나타낸다.

  • RSV1 옵션 1
  • RSV2 : 옵션 2
  • RSV3 : 옵션 3
  • OptCode은 : 프레임의 타입을 나타낸다.

125 바이트보다 작은 문자 메시지를 보내려면 메시지에 90 바이트가 있다고 가정하고 첫 번째 바이트에는 비트 0을 1 (중요), 다음 3을 0, 옵션을 사용 가능하게하고 싶지 않다면 다음 4는 0001이되어 텍스트 프레임을 나타냅니다. 따라서 첫 번째 바이트는 10000001 또는 129가됩니다.

이제 두 번째 바이트에서 첫 번째 비트는 프레임이 마스크되는지 여부를 나타냅니다. 서버에서 클라이언트로 프레임을 마스크하지 않으므로 0을 설정합니다. 다음 7 비트는 길이 또는 프레임 길이 형식을 나타냅니다. 작은 프레임을 보내므로이 7 비트에 최대 125 개의 값을 표시 할 수 있습니다. 따라서 프레임 길이가 90 바이트이기 때문에 헤더의 두 번째 바이트는 01011010 또는 90이됩니다.

따라서 서버에서 클라이언트로 90 바이트의 텍스트 프레임을 보낼 때 헤더를 따르는 처음 두 바이트는 129와 90이됩니다. 나머지 메시지는 90 바이트의 UTF8로 인코딩 된 바이트가됩니다.

프레임이 125 바이트보다 길면 헤더의 길이도 같습니다. 사양을 확인하십시오. 프레임이 마스킹되어야하는 경우 (예 : 클라이언트에서 가져온 프레임과 같은 경우), 본문의 처음 4 바이트는 마스킹 키를 포함합니다. 당신이 볼 수 있듯이 몇 가지 맛있는 가벼운 음식이 있으므로 추천서를 읽어 보길 권합니다. https://tools.ietf.org/html/rfc6455

+0

그래, 지금까지 2 ~ 3 번 보았지만 프레임을 'byte []'로 구조화하는 방법을 잘 모른다. 나는 그것이 텍스트 패킷이기 때문에 첫 번째 바이트가 1이 될 것이라는 것을 알고 있지만, 그 후에 무엇을해야합니까? –

+0

정말로 내 업데이트를 확인하십시오. 작은 텍스트 프레임의 머리글을 작성하는 방법을 설명합니다. – vtortola

관련 문제