websocket握手问题 [英] websocket handshake problem

查看:35
本文介绍了websocket握手问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using python to implement a simple websocket server. The handshake I'm using comes from http://en.wikipedia.org/w/index.php?title=WebSockets&oldid=372387414.

握手本身似乎有效,但是当我点击发送时,我收到一个 javascript 错误:

The handshake itself seems to work, but when I hit send, I get a javascript error:

未捕获的错误:INVALID_STATE_ERR:DOM 异常 11

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代码:

And here's the python code:

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

有谁知道我在这里做错了什么?

Does anyone know what I'm doing wrong here?

推荐答案

我在 Firefox 4 上测试了你的代码并在点击发送时遇到了同样的错误,但在此之前我得到了

I tested your code on Firefox 4 and got the same error upon hitting send, however before that I got

Firefox 无法建立连接到 ws://localhost:8888/的服务器.

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

这可能就是 WebSocket 对象被销毁的原因.我怀疑您的握手响应缺少某些内容,因此 Firefox 正在关闭套接字.

which is probably why the WebSocket object was destroyed. I suspect your handshake response is missing something, so Firefox is closing the socket.

来自维基百科关于 Websockets 的文章:

From the Wikipedia article on Websockets:

Sec-WebSocket-Key1 和Sec-WebSocket-Key2 字段和字段后的八个字节服务器使用的随机令牌最后构造一个 16 字节的令牌它的握手证明它有读取客户端的握手.

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.

您服务器的响应底部没有这个特殊数字,所以我认为我们需要弄清楚如何生成它,并将其包含在内.

Your server's response does not have this special number at the bottom, So I think we need to figure out how to generate it, and include it.

如何生成该数字

让我们从key1、key2和握手结束的8个字节开始

Lets start with key1, key2, and the 8 bytes at the end of the handshake

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 中:

We make a number for each key by ignoring every character that is not a digit 0-9. In Python:

def numFromKey(key):
    return int(filter(lambda c: c in map(str,range(10)),key))

接下来我们将该数字除以原始键字符串中的空格数,因此这里是一个计算字符串中空格数的函数.

next we divide that number by the number of spaces in the original key string, so here is a is a function that counts the spaces in a string.

def spacesIn(key):
    return len(filter(lambda c: c==' ',key))

由键产生的两个数字是:

The two numbers resulting from the keys are:

pkey1 = numFromKey(key1)/spacesIn(key1)
pkey2 = numFromKey(key2)/spacesIn(key2)

现在我们需要连接 pkey1、pkey2 和 end8 的字节.处理后的密钥需要表示为 32 位 Big-Endian 数字.

Now we need to concatenate the bytes of pkey1, pkey2, and end8. The processed keys need to be represented as 32 bit Big-Endian numbers.

from struct import pack
catstring = pack('>L',pkey1) + pack('>L',pkey2) + end8

然后我们取这些字节的 md5 哈希值来获得我们在握手结束时添加的幻数

Then we take the md5 hash of those bytes to get the magic number that we tack on the end of the handshake

import md5
magic = md5.new(catstring).digest()

我认为它至少是这样工作的

Thats how I think it works at least

这篇关于websocket握手问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆