使用Python服务器的Websocket握手问题

问题描述:

这是关于在Websocket Protocol 76中握手的问题。使用Python服务器的Websocket握手问题

我写了一个客户端和服务器,但在客户端 接受握手时遇到了问题。我可以看到它正在返回,但客户端立即关闭连接。我猜测我的md5sum响应必须是错误的。

据我所知,我遵循正确的程序,任何人都可以告诉我我做错了什么?

def create_handshake_resp(handshake): 

    # parse request 
    final_line = "" 
    lines = handshake.splitlines() 
    for line in lines: 
    parts = line.partition(":") 
    if parts[0] == "Sec-WebSocket-Key1": 
     key1 = parts[2] 
    elif parts[0] == "Sec-WebSocket-Key2": 
     key2 = parts[2] 
    final_line = line 

    #concat the keys and encrypt 
    e = hashlib.md5() 
    e.update(parse_key(key1)) 
    e.update(parse_key(key2)) 
    e.update(final_line) 
    return "HTTP/1.1 101 WebSocket Protocol Handshake\r\nUpgrade: WebSocket\r\nConnection:  Upgrade\r\nWebSocket-Origin: http://%s\r\nWebSocket-Location: ws://%s/\r\nWebSocket-Protocol: sample\r\n\r\n%s" % (httphost, sockethost, e.digest()) 



def parse_key(key): 

    spaces = -1 
    digits = "" 
    for c in key: 
    if c == " ": 
     spaces += 1 
    if is_number(c): 
     digits = digits + c 


    new_key = int(digits)/spaces 
    return str(new_key) 

正如你所看到的,我表演什么,我认为是在按键上的正确操作(数字除以由空间计数,CONCAT结果和请求,然后MD5的最后一行),以及16字节回应肯定是返回。

任何帮助将不胜感激,只要我有工作副本,我会在这里发布。

谢谢。

编辑:

更改标头符合kanaka的回应。握手仍然没有被客户接受。 我发现了如何显示铬的请求,这是被赋予请求和响应:

(P) t=1291739663323 [st=3101]  WEB_SOCKET_SEND_REQUEST_HEADERS 
           --> GET/HTTP/1.1 
            Upgrade: WebSocket 
            Connection: Upgrade 
            Host: --- 
            Origin: http://--- 
            Sec-WebSocket-Key1: 3E 203C 220 642; 
            Sec-WebSocket-Key2: Lg 590 ~5 703O G7 =%t 9 

            \x74\x66\xef\xab\x50\x60\x35\xc6\x0a 
(P) t=1291739663324 [st=3102]  SOCKET_STREAM_SENT  
(P) t=1291739663348 [st=3126]  SOCKET_STREAM_RECEIVED 
(P) t=1291739663348 [st=3126]  WEB_SOCKET_READ_RESPONSE_HEADERS 
           --> HTTP/1.1 101 WebSocket Protocol Handshake 
            Upgrade: WebSocket 
            Connection: Upgrade 
            Sec-WebSocket-Origin: http://--- 
            Sec-WebSocket-Location: ws://---/ 
            Sec-WebSocket-Protocol: sample 

            \xe7\x6f\xb9\xcf\xae\x70\x57\x43\xc6\x20\x85\xe7\x39\x2e\x83\xec\x0 

广告一字不差,但我已删除的原因很明显的IP地址。

+0

您的压痕没有意义。我认为#`concat`..``return`行应该在`create_handshake_resp`中? – 2010-12-07 01:42:01

+0

对不起。复制并粘贴错误。编辑。 – Jivings 2010-12-07 08:25:44

你有几个问题,立即在我跳出:

  • 您没有正确计算空间。你的计数器应该从0开始而不是-1。
  • 您的回复标题仍然是v75风格。任何以“WebSocket-”(WebSocket-Origin,WebSocket-Location,WebSocket-Protocol)开头的头文件应该在v76中以“Sec-WebSocket-”开头。

这是我如何计算在wsproxy响应CHKSUM(的noVNC一部分的HTML5 VNC客户端):

import struct, md5 
... 
spaces1 = key1.count(" ") 
spaces2 = key2.count(" ") 
num1 = int("".join([c for c in key1 if c.isdigit()]))/spaces1 
num2 = int("".join([c for c in key2 if c.isdigit()]))/spaces2 

return md5(struct.pack('>II8s', num1, num2, key3)).digest() 

这里是一个网页套接字的客户机/服务器(客户端在Javascript,服务器的工作示例在Python 2.6)

它使用的例子从不同的地方(包括kanaka的答案/ noVNC和this pagethis page

支援Google Chrome 10.0.648.127,Safari浏览器5.0.3和MobileSafari上的iPad的iOS 4.3

这绝不是好写的代码(例子中的HTML页面特别可怕) - 使用您自己的风险等..

#!/usr/bin/env python 

import socket 
import threading 
import struct 
import hashlib 

PORT = 9876 


def create_handshake_resp(handshake): 
    final_line = "" 
    lines = handshake.splitlines() 
    for line in lines: 
     parts = line.partition(": ") 
     if parts[0] == "Sec-WebSocket-Key1": 
      key1 = parts[2] 
     elif parts[0] == "Sec-WebSocket-Key2": 
      key2 = parts[2] 
     elif parts[0] == "Host": 
      host = parts[2] 
     elif parts[0] == "Origin": 
      origin = parts[2] 
     final_line = line 

    spaces1 = key1.count(" ") 
    spaces2 = key2.count(" ") 
    num1 = int("".join([c for c in key1 if c.isdigit()]))/spaces1 
    num2 = int("".join([c for c in key2 if c.isdigit()]))/spaces2 

    token = hashlib.md5(struct.pack('>II8s', num1, num2, final_line)).digest() 

    return (
     "HTTP/1.1 101 WebSocket Protocol Handshake\r\n" 
     "Upgrade: WebSocket\r\n" 
     "Connection: Upgrade\r\n" 
     "Sec-WebSocket-Origin: %s\r\n" 
     "Sec-WebSocket-Location: ws://%s/\r\n" 
     "\r\n" 
     "%s") % (
     origin, host, token) 


def handle(s, addr): 
    data = s.recv(1024) 
    s.send(create_handshake_resp(data)) 
    lock = threading.Lock() 

    while 1: 
     print "Waiting for data from", s, addr 
     data = s.recv(1024) 
     print "Done" 
     if not data: 
      print "No data" 
      break 

     print 'Data from', addr, ':', data 

     # Broadcast received data to all clients 
     lock.acquire() 
     [conn.send(data) for conn in clients] 
     lock.release() 

    print 'Client closed:', addr 
    lock.acquire() 
    clients.remove(s) 
    lock.release() 
    s.close() 

def start_server(): 
    s = socket.socket() 
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
    s.bind(('', PORT)) 
    s.listen(1) 
    while 1: 
     conn, addr = s.accept() 
     print 'Connected by', addr 
     clients.append(conn) 
     threading.Thread(target = handle, args = (conn, addr)).start() 

clients = [] 
start_server() 

而且,一个蹩脚的例子HTML页面来显示它的工作:

<!DOCTYPE html> 
<html lang="en"> 
    <head> 
     <title>Test</title> 
     <script type="application/javascript"> 
      var ws; 

      function init() { 
       var servermsg = document.getElementById("servermsg"); 

       ws = new WebSocket("ws://localhost:9876/"); 
       ws.onopen = function(){ 
        servermsg.innerHTML = servermsg.innerHTML + "<br>Server connected"; 
        servermsg.innerHTML = servermsg.innerHTML + "<br>Sending message to server"; 
        ws.send("Hello Mr. Server!"); 
       }; 
       ws.onmessage = function(e){ 
        servermsg.innerHTML = servermsg.innerHTML + "<br>Recieved data: " + e.data; 
       }; 
       ws.onclose = function(){ 
        console.log("Server disconnected"); 
        servermsg.innerHTML = servermsg.innerHTML + "<br>Connected"; 
       }; 
      } 
      function postmsg(){ 
       var text = document.getElementById("message").value; 
       ws.send(text); 
       servermsg.innerHTML = servermsg.innerHTML + "<br>Sent: " + text; 
       return false; 
      } 
     </script> 
    </head> 
    <body onload="init();"> 
     <form action="" onSubmit="postmsg()"> 
      <input type="text" name="message" value="" id="message"> 
      <input type="submit" name="submit" value="" id="submit"> 
     </form> 
     <div id="servermsg"><h1>Message log:</h1></div> 
    </body> 
</html>