Рукопожатие Python WebSocket (RFC 6455)

Я пытаюсь реализовать простой сервер websoket на python, используя протокол RFC 6455. Я взял формат рукопожатия здесь и здесь.

Я использую Chromium 17 и Firefox 11 в качестве клиентов и получаю эту ошибку:

Uncaught Error: INVALID_STATE_ERR: DOM Exception 11

Я ожидаю увидеть hello from server в моем браузере и hello from client в журнале сервера.

Я думаю, мое рукопожатие не так, вы можете указать мне на мою ошибку?

Журнал сервера, запрос:

GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: 127.0.0.1:8999
Origin: null
Sec-WebSocket-Key: 8rYWWxsBPEigeGKDRNOndg==
Sec-WebSocket-Version: 13

Журнал сервера, ответ:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: 3aDXXmPbE5e9i08zb9mygfPlCVw=

Необработанный ответ:

HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: 3aDXXmPbE5e9i08zb9mygfPlCVw=\r\n\r\n

Код сервера:

import socket
import re
from base64 import b64encode
from hashlib import sha1

websocket_answer = (
    'HTTP/1.1 101 Switching Protocols',
    'Upgrade: websocket',
    'Connection: Upgrade',
    'Sec-WebSocket-Accept: {key}\r\n\r\n',
)

GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('127.0.0.1', 8999))
s.listen(1)

client, address = s.accept()
text = client.recv(1024)
print text

key = (re.search('Sec-WebSocket-Key:\s+(.*?)[\n\r]+', text)
    .groups()[0]
    .strip())

response_key = b64encode(sha1(key + GUID).digest())
response = '\r\n'.join(websocket_answer).format(key=response_key)

print response
client.send(response)

print client.recv(1024)
client.send('hello from server')

Код клиента:

<!DOCTYPE html>
<html>
<head>
    <title>test</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <script type="text/javascript">
        var s = new WebSocket('ws://127.0.0.1:8999');
        s.onmessage = function(t){alert(t)};
        s.send('hello from client');
    </script>
</head>
<body>
</body>
</html>

2 ответа

Решение

Ваш сервер рукопожатия код выглядит хорошо.

Код клиента выглядит так, как будто он попытается отправить сообщение до того, как (асинхронное) рукопожатие завершится. Вы можете избежать этого, переместив свое сообщение send в метод onopen вашего websocket.

Как только соединение установлено, сервер не отправляет и не получает сообщения в виде простого текста. Подробности смотрите в разделе описания данных в спецификации. (Код клиента может игнорировать это, так как браузер позаботится о создании данных для вас.)

Я пробовал то же самое, но так и не смог заставить это работать. В конце концов я нашел статью « Библиотека для создания серверов и клиентов WebSocket на Python» от Эймерика Огюстина . То, как он это делает (код ниже), автоматически передает вам рукопожатие.

      import asyncio
import websockets

async def echo(websocket, path):
    async for message in websocket:
        await websocket.send(message)

asyncio.get_event_loop().run_until_complete(websockets.serve(echo, 'localhost', 8765))
asyncio.get_event_loop().run_forever()
Другие вопросы по тегам