我正在使用的握手来自 http://en.wikipedia.org/w/index.php?title=WebSockets&oldid=372387414.
握手本身似乎有效,但是当我点击发送时,我收到一个javascript错误:
Uncaught Error: INVALID_STATE_ERR: DOM Exception 11
这是html:
<!doctype html> <html> <head> <title>ws_json</title> </head> <body onload="handleLoad();" onunload="handleUnload();"> <input type="text" id='input' /> <input type="button" value="submit" onclick="handleSubmit()" /> <div id="display"></div> <script type="text/javascript"> function showmsg(str){ display = document.getElementById("display"); display.innerHTML += "<p>" + str + "</p>"; } function send(str){ ws.send(str.length); ws.send(str); } function handleSubmit(){ input = document.getElementById('input'); send(input.value); input.focus(); input.value = ''; } function handleLoad(){ ws = new WebSocket("ws://localhost:8888/"); ws.onopen = function(){ showmsg("websocket opened."); } ws.onclose = function(){ showmsg("websocket closed."); } } function handleUnload(){ ws.close(); } </script> </body> </html>
这是python代码:
import socket import threading import json PORT = 8888 LOCATION = "localhost:8888" def handler(s): print " in handler " ip,_ = s.getpeername() print "New connection from %s" % ip request = s.recv(1024) print "\n%s\n" % request print s.getpeername() # send response response = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" response += "Upgrade: WebSocket\r\n" response += "Connection: Upgrade\r\n" try: peername = s.getpeername() response += "Sec-WebSocket-Origin: http://%s\r\n" % peername[0] # % request[request.index("Origin: ")+8:-4] except ValueError: print "Bad Request" raise socket.error response += "Sec-WebSocket-Location: ws://%s\r\n" % LOCATION response += "Sec-WebSocket-Protocol: sample" response = response.strip() + "\r\n\r\n" print response s.send(response) while True: length = s.recv(1) print length if not length: break length = int(length) print "Length: %i" % length data = s.recv(length) print "Received: %s" % data print "" s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) s.bind(('localhost',PORT)) s.listen(5) print "server is running..." while True: sock,addr = s.accept() threading.Thread(target=handler,args=(sock,)).start()
有谁知道我在这里做错了什么?
解决方法
Firefox can’t establish a connection
to the server at ws://localhost:8888/.
这可能是WebSocket对象被销毁的原因.我怀疑你的握手响应丢失了,所以Firefox正在关闭套接字.
来自Wikipedia上关于Websockets的文章:
The Sec-WebSocket-Key1 and
Sec-WebSocket-Key2 fields and the
eight bytes after the fields are
random tokens which the server uses to
construct a 16 byte token at the end
of its handshake to prove that it has
read the client’s handshake.
您的服务器响应底部没有此特殊编号,因此我认为我们需要弄清楚如何生成它并包含它.
编辑:如何生成该数字
让我们从key1,key2和握手结束时的8个字节开始
key1 = "18x 6]8vM;54 *(5: { U1]8 z [ 8" key2 = "1_ tx7X d < nw 334J702) 7]o}` 0" end8 = "Tm[K T2u"
我们通过忽略每个不是数字0-9的字符为每个键创建一个数字.在Python中:
def numFromKey(key): return int(filter(lambda c: c in map(str,range(10)),key))
接下来我们将该数字除以原始键字符串中的空格数,因此这里是一个计算字符串中空格的函数.
def spacesIn(key): return len(filter(lambda c: c==' ',key))
键产生的两个数字是:
pkey1 = numFromKey(key1)/spacesIn(key1) pkey2 = numFromKey(key2)/spacesIn(key2)
现在我们需要连接pkey1,pkey2和end8的字节.处理后的密钥需要表示为32位Big-Endian数字.
from struct import pack catstring = pack('>L',pkey1) + pack('>L',pkey2) + end8
然后我们采用这些字节的md5哈希值来获得在握手结束时我们处理的幻数
import md5 magic = md5.new(catstring).digest()
多数民众赞成我认为它至少有用