2016-11-17 4 views
0

Я пытаюсь сделать подключение к веб-соке между клиентом javascript и сервером python. Мне удалось получить право на связь, и я могу отправлять данные с javascript-клиента и декодировать его на сервере.Python encode web socket frames

Проблема возникает, когда я хочу отправить данные с сервера. Когда я пытаюсь отправить чистый текст ascii, я получаю эту ошибку на клиенте Websocket Error: [object Event]. Естественно, поэтому я хочу «закодировать» данные перед отправкой. Я пробовал много вещей, включая базовый base64. Но ничего не работает. Я наткнулся на это thread. Где это пример того, как подготовить данные для отправки.

Вот код, я придумал до сих пор:

def encodeFrame(bytesRaw): 
bytesFormatted = [] 
bytesFormatted.append(129) 

indexStartRawData = 0 

if len(bytesRaw) <= 125: 
    bytesFormatted.append(len(bytesRaw)) 

    indexStartRawData = 2 

elif len(bytesRaw) >= 126 and len(bytesRaw) <= 65535: 
    bytesFormatted.append(126) 
    bytesFormatted.append((len(bytesRaw) >> 8) + 255) 
    bytesFormatted.append((len(bytesRaw)) + 255) 

    indexStartRawData = 4 

else: 
    bytesFormatted.append(127) 
    bytesFormatted.append((len(bytesRaw) >> 56) + 255) 
    bytesFormatted.append((len(bytesRaw) >> 48) + 255) 
    bytesFormatted.append((len(bytesRaw) >> 40) + 255) 
    bytesFormatted.append((len(bytesRaw) >> 32) + 255) 
    bytesFormatted.append((len(bytesRaw) >> 24) + 255) 
    bytesFormatted.append((len(bytesRaw) >> 16) + 255) 
    bytesFormatted.append((len(bytesRaw) >> 8) + 255) 
    bytesFormatted.append((len(bytesRaw)) + 255) 

    indexStartRawData = 10 

bytesFormatted.put(bytesRaw, indexStartRawData) 

return bytesFormatted 

Я думаю, что большинство из них работает правильно, но я понятия не имею, что я должен делать с последней командой: bytesFormatted.put(bytesRaw, indexStartRawData). Я попытался просто добавить к массиву и использовать буферный формат. Но это не сработает. Функция, которая отправляет данные client.send(encodeFrame("test")) в моем случае, принимает только буфер или строку.

Кто-нибудь знает, как это сделать «кодирование»?

ответ

1

Я не следую за этими (len(bytesRaw) >> 32) + 255 линиями. Например, если длина полезной нагрузки 70'000, else пункт будет выполнен, что дает вам последовательность

[127, 255, 255, 255, 255, 255, 256, 528, 70255] 

это не имеет большого смысла для меня. Фактически, ссылка, которую вы указали, предлагает использовать операцию binary AND, в то время как вы используете арифметику + (вы можете использовать +, если вы должны выполнить двоичный код OR для чисел с неперекрывающимися 1 в двоичной форме, но не для выполнения AND). Это очень разные операции!

Несмотря на то, что вы можете использовать (len(bytesRaw) >> 32) & 255, это не гарантирует, что номер будет длиться по одному байту - переводчик должен решить, как его сохранить. Чтобы преодолеть это, модуль struct в python используется для сборки двоичных данных. Например, вся статья else обрушивается на struct.pack('B', 127) + struct.pack('!Q', len(bytesRaw)). ! означает, что порядок байтов сети (big-endian), Q означает 8-байтовое целое без знака, B означает беззнаковый байт.

Даже если вы не хотите, чтобы переписать код с struct (я не настаиваю, конечно), в настоящее время вы возвращаете list из encodeFrame функции. Вы не можете отправить список по сети. Вы можете отправить массив C, но список Python - очень сложный объект и не может быть отправлен таким образом. Вы должны преобразовать его в последовательность байт первого:

def list_to_bytes(lst): 
    format = 'B' * len(lst) 
    return struct.pack(format, *lst) 

Также, пожалуйста, не забывайте, что ваша полезная нагрузка должна быть допустимую строку UTF-8, так как вы используете текстовые фреймы. Для получения дополнительной информации см. RFC 6455.

+0

Спасибо, работает отлично! – jakobS