2010-07-10 212 views
7

我正在使用python来实现一个简单的websocket服务器。 我使用的握手来自http://en.wikipedia.org/w/index.php?title=WebSockets&oldid=372387414websocket握手问题

握手本身似乎工作,但是当我点击发送,我得到一个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() 

有没有人知道我在做什么错在这里?

+0

我无法在没有WebSocket类的情况下测试您的代码。它在哪里定义? Firefox 3.6.3似乎并不知道它是什么。 – Nathan 2010-07-12 20:18:04

+0

Chrome Dev有它,而Firefox 4应该有它。 – lowerkey 2010-07-12 21:22:34

+0

如果您没有100位代表,您是如何提供赏金的? – Nathan 2010-07-13 17:14:48

回答

6

我测试你的代码在Firefox 4和击球时发出了同样的错误,但是之前我得到

Firefox can't establish a connection to the server at ws://localhost:8888/.

这可能是为什么WebSocket的对象已受到破坏。我怀疑你的握手响应缺少一些东西,所以Firefox正在关闭套接字。

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

那结束时,我怎么想它的工作原理至少

+0

感谢您的信息,从来没有想过自己。我在谷歌上发现了这个:http://golang.org/src/pkg/websocket/server.go它描述了如何生成密钥。在我们发言时努力理解它。 – lowerkey 2010-07-13 22:16:06

+0

下面是握手的更好的描述:http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76#page-7 – lowerkey 2010-07-13 22:58:27

+1

我来到了一个类似的解决方案,但我有问题编码的结果utf-8中的md5算法。 – lowerkey 2010-07-14 23:11:40