2015-12-02 3 views
0

Я пишу реализацию веб-сокета C# и всякий раз, когда я отправляю сообщения размером более 65535 байт; клиент (Javascript) не может загрузить сообщение и закрывает соединение. (Ранее говоря недействительный кадр, теперь он ничего не говорит)Websocket закрывается большими сообщениями

Я кодирующая сообщения, как так

public 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; 
    } 

сообщения под 65535 байт отправить штраф. Любая помощь приветствуется.

Чтобы прояснить сообщение, которое пытается отправить, составляет 120283 байт; код ошибки 1006

Для сообщений длиной до 125 байт код верен. Для сообщений> 125, но < = 65536 байт, мне нужно написать 3 байта - первый байт - 126; следующие 2 байта дают длину сообщения. Для сообщений> 65536 байт мне нужно записать 9 байтов - первый байт равен 127; длина сообщения составляет 8 байтов.

Как вы можете видеть, я делаю все это в приведенном выше коде, но сообщение не удается отправить.

+0

Вы смотрите, как вы бы пользу от EndianBitConverter от Jon Skeet в [miscutil] (http://jonskeet.uk/csharp/miscutil/) ([nuget] (https://www.nuget.org/packages/JonSkeet.MiscUtil/)) Это сделает ваш код несколько легче читать. – spender

ответ

3

Похоже, что есть ошибка в этом:

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); 

Это потому, что вы пытаетесь Bitshift номер 32bit более 8 байт, даже если Int32 имеет длину всего 4 байта. Чистый результат, вы в конечном итоге сохраняете один и тот же 32-битный номер дважды над 8 байтами. Вы можете конвертировать length в ulong и использовать это значение вместо этого, а ваш код должен работы. В противном случае ...

Я предпочитаю использовать чужой код для чего-то такого же скучного, как битгифтинг.

Этот код битрейта (и его ошибки) распространяется по всему миру (вы не первый человек, который видит эту проблему).

Если вы захватить MiscUtil Jon тарелочкам от nuget, вы получите лучший результат со следующим кодом (с дополнительным бонусом, что это гораздо легче читать):

frame[1] = (byte)127; 
EndianBitConverter.Big.CopyBytes((ulong)length, frame, 2); 
+0

Великолепный, фиксированный. Я сам не был поклонником оригинального кода, поэтому это приветствуемое изменение. – user3037561

+0

@ user3037561 Я выяснил, почему оригинал был ранен ... – spender

Смежные вопросы