Python WebSocket握手(RFC 6455)

7
我正在尝试使用RFC 6455协议在Python上实现一个简单的WebSocket服务器。我从这里这里获取握手格式。
我使用Chromium 17和Firefox 11作为客户端,并收到以下错误:Uncaught Error: INVALID_STATE_ERR: DOM Exception 11 我期望在我的浏览器中看到来自服务器的hello,并在服务器日志中看到来自客户端的hello
我猜想我的握手有误,请帮我指出错误。
##服务器日志,请求:
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>

除非是为了学习它的工作原理,否则我不会自己实现WebSockets。已经存在现有的实现,例如http://code.google.com/p/pywebsocket/。 - ThiefMaster
4
我想学习并理解基础知识,然后再开始使用库。 - John Smith
2个回答

5

您的服务器握手代码看起来很好。

然而,客户端代码似乎会在(异步)握手完成之前尝试发送消息。您可以通过将消息发送移动到websocket的onopen方法中来避免这种情况。

一旦建立连接,服务器不会以纯文本形式发送或接收消息。有关详细信息,请参见规范中的数据帧部分。(客户端代码可以忽略此内容,因为浏览器会为您处理数据帧。)


非常感谢。我在不断地搜索服务器代码中的错误,结果发现是客户端的问题。 - John Smith

0

我也曾尝试过同样的事情,但始终无法使其正常工作。最终,我找到了一篇文章Python中用于构建WebSocket服务器和客户端的库,作者为Aymeric Augustin。他的方法(下面的代码)可以自动为您完成握手。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接