python websocket握手(RFC 6455)
Posted
技术标签:
【中文标题】python websocket握手(RFC 6455)【英文标题】:python websocket handshake (RFC 6455) 【发布时间】:2012-04-14 08:50:30 【问题描述】:我正在尝试使用 RFC 6455 协议在 python 上实现一个简单的 websoket 服务器。 我采用了here 和here 的握手格式。
我使用 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>
【问题讨论】:
除非是为了学习它是如何工作的,否则我不会自己实现 websockets。现有的实现如code.google.com/p/pywebsocket 它完全是为了学习。在开始使用库之前,我想了解和了解基础知识 【参考方案1】:您的服务器握手代码看起来不错。
客户端代码看起来会在(异步)握手完成之前尝试发送消息。您可以通过将消息发送移动到 websocket 的 onopen 方法来避免这种情况。
一旦建立连接,服务器就不会以纯文本形式发送或接收消息。有关详细信息,请参阅规范的 data framing 部分。 (客户端代码可以忽略这一点,因为浏览器会为您处理数据框架。)
【讨论】:
非常感谢。我一直在寻找服务器代码中的错误,它在客户端中。 支持@simonc。想法和流程是正确的。详细描述:the-eye.eu/public/Books/IT%20Various/… 并且不要忘记 'Sec-WebSocket-Protocol' 标头。【参考方案2】:我也在尝试同样的事情,但始终无法正常工作。最后我找到了一篇文章Library for building WebSocket servers and clients in Python by 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()
【讨论】:
以上是关于python websocket握手(RFC 6455)的主要内容,如果未能解决你的问题,请参考以下文章